分类 编程及辅助 下的文章

Perl的模块、包和跨文件的函数调用


Perl 子程序(函数)

Perl 子程序可以出现在程序的任何地方,语法格式如下:

sub subroutine{
   statements;
}

调用子程序语法格式

subroutine( 参数列表 );

在 Perl 5.0 以下版本调用子程序方法如下

&subroutine( 参数列表 );
向子程序传递参数

Perl 子程序可以和其他编程一样接受多个参数,子程序参数使用特殊数组 @_ 标明。

因此子程序第一个参数为 $_[0], 第二个参数为 $_[1], 以此类推。

不论参数是标量型还是数组型的,用户把参数传给子程序时,perl默认按引用的方式调用它们。

子程序返回值

子程序可以向其他编程语言一样使用 return 语句来返回函数值。

如果没有使用 return 语句,则子程序的最后一行语句将作为返回值。

#!/usr/bin/perl

# 方法定义
sub add_a_b{
   # 不使用 return
   $_[0]+$_[1];  

   # 使用 return
   # return $_[0]+$_[1];  
}
print add_a_b(1, 2)
Perl 包和模块

Perl 中每个包有一个单独的符号表,定义语法为:

package mypack;

例子程序:

文件名为db_operate.pm的库perl文件

#!/usr/bin/perl -w

use strict;
use DBI;

package sql;
sub execute {
        my $host = "localhost";
        my $driver = "Pg";
        my $database = "library";
        my $user = "admin";
        my $passwd = "157359";

        my $stmt = $_[0];
        my $dsn = "DBI:$driver:dbname=$database;host=127.0.0.1;port=5432";;
        my $dbh = DBI->connect($dsn,$user,$passwd) or die $DBI::errstr;
        my $sth = $dbh->prepare($stmt);
        $sth->execute();

        my @array;
        while ( my @row = $sth->fetchrow_array() ) {
                push(@array,[@row]);
        }

        return @array;

        $sth->finish();
        $dbh->disconnect;

}
1;              #不添加执行db_test.cgi时会出现错误db_operate.pm did not return a true value at db_test.cgi line 7.
                #                              BEGIN failed--compilation aborted at db_test.cgi line 7.

文件名为db_test.cgi文件去调用模块文件db_operate.pm中的包sql里的execute函数,传入参数为$sql,传出参数为@array:

#!/usr/bin/perl -w

use strict;
use JSON;
use CGI;
use Encode;
use db_operate;   #调用模块文件db_operate.pm,还可用require函数调用文件,但是其调用方式为require db_operate.om;

my $sql = "select * from lib_user";
my @array = sql::execute($sql);        #调用sql包中的execute函数,其参数为$sql
my $json = decode_utf8(encode_json \@array);
my $q = new CGI;
print $q->header(-charset=>'utf-8',-type=>'application/json');
print $json;

Perl连接PostgreSQL数据库


变量名约定

以下设置了比较常用的变量名命名方法:

$dsn    驱动程序对象的句柄
$dbh    一个数据库对象的句柄
$sth    一个语句或者一个查询对象的句柄
$h      通用的句柄 ($dbh, $sth, 或 $drh),依赖于上下文
$rc     操作代码返回的布什值(true 或 false)
$rv     操作代码返回的整数值
@ary    查询返回的一行值的数组(列表)
$rows   操作代码返回的行数值
$fh     文件句柄
undef   NULL 值表示未定义
\%attr  引用属性的哈希值并传到方法上

数据库连接

#!/usr/bin/perl

use DBI;
use strict;

my $driver   = "Pg"; 
my $database = "testdb";
my $dsn = "DBI:$driver:dbname=$database;host=127.0.0.1;port=5432";  #这里要注意:;
my $userid = "admin";
my $password = "157359";
my $dbh = DBI->connect($dsn, $userid, $password) or die $DBI::errstr;

print "Opened database successfully\n";

DBI的API说明:

DBI->connect($data_source, "userid", "password", %attr)
建立数据库连接或会话,请求数据源。如果连接成功,则返回一个数据库句柄对象。

数据源的形式如 : DBI:Pg:dbname=$database;host=127.0.0.1;port=5432
PG是PostgreSQL驱动程序名称,testdb的数据库的名称。

在本机测试封装包的db_operate.pm:

#!/usr/bin/perl -w

use strict;
use DBI;

package sql;
sub execute {
        my $host = "localhost";
        my $driver = "Pg";
        my $database = "library";
        my $user = "admin";
        my $passwd = "157359";

        my $stmt = $_[0];
        my $dsn = "DBI:$driver:dbname=$database;host=127.0.0.1;port=5432";;
        my $dbh = DBI->connect($dsn,$user,$passwd) or die $DBI::errstr;
        my $sth = $dbh->prepare($stmt);
        $sth->execute();

        my @array;
        while ( my @row = $sth->fetchrow_array() ) {
                push(@array,[@row]);
        }

        return @array;

        $sth->finish();
        $dbh->disconnect;

}
1;

Perl-CGI脚本网页输出的时候Internal Server Error


网页访问CGI文件时出现错误,错误如下

Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.
More information about this error may be available in the server error log.

主要是引文CGI文件中没有输出header头文件:

#!/usr/bin/perl
use JSON;

my $q = new CGI;
my %rec_hash = ('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
my $json = encode_json \%rec_hash;
print "$json";

添加以下几行即可解决:

use CGI;
my $q = new CGI;
print $q->header();

在终端会输出html的部分头:

[root@bogon cgi-bin]# perl test.cgi
Content-Type: application/json; charset=UTF-8

{"e":5,"c":3,"a":1,"b":2,"d":4}

Linux命令行下获取本机外网ip的几种方法


Curl 纯文本格式输出:

curl icanhazip.com
curl ifconfig.me
curl curlmyip.com
curl ip.appspot.com
curl ipinfo.io/ip  这个不错
curl ipecho.net/plain
curl www.trackip.net/i

curl JSON格式输出:

curl ipinfo.io/json
curl ifconfig.me/all.json
curl www.trackip.net/ip?json (有点丑陋)

curl XML格式输出:

curl ifconfig.me/all.xml

curl 得到所有IP细节 (挖掘机)

curl ifconfig.me/all

使用 DYDNS (当你使用 DYDNS 服务时有用)

curl -s 'http://checkip.dyndns.org' | sed 's/.*Current IP Address: \([0-9\.]*\).*/\1/g'
curl -s http://checkip.dyndns.org/ | grep -o "[[:digit:].]\+"

使用 Wget 代替 Curl

wget http://ipecho.net/plain -O - -q ; echo
wget http://observebox.com/ip -O - -q ; echo

使用 host 和 dig 命令

如果有的话,你也可以直接使用 host 和 dig 命令。

host -t a dartsclink.com | sed 's/.*has address //'
dig +short myip.opendns.com @resolver1.opendns.com

bash 脚本示例:

#!/bin/bash
PUBLIC_IP=`wget http://ipecho.net/plain -O - -q ; echo`
echo $PUBLIC_IP

Tampermonkey 脚本编写


室友推荐了个chrome的插件,我就发现了这东西好像有毒,原来网页还能加东西呢,就有了一个想法:

让每个网页都显示对应网址的IP地址和其他详细的信息。

第一件事就是给chrome添加Tampermonkey插件,然后添加脚本,虽然网上有挺多大神的脚本,但是本着发扬光大的思想......

来,我们看看添加新的脚本:

// ==UserScript==
// @name New Userscript //插件名字
// @namespace http://tampermonkey.net/  //插件所属名
// @version 0.1  //版本
// @description try to take over the world!
// @author You
// @match http:/// //地址范围
// @grant none  //
// ==/UserScript==

(function() {

'use strict';

// Your code here...

})();

再添一个jQ库,方便:

// @require http://code.jquery.com/jquery-1.11.0.min.js

在// your code here写我们想写js代码

先测试一下,在网页中加个文字:

// ==UserScript==
// @name test
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match *
// @grant none
// ==/UserScript==

(function() {

'use strict';

var div_test = document.createElement("div");
div_test.setAttribute("id", "id_test");
var a = document.body;
a.insertBefore(div_test, a.firstChild);
document.getElementById('id_test').innerHTML = 'test';

})();

Screenshot-at-2017-04-13-10-21-36.png

继续,那就直接去实现前面的想法,把比较详细的IP信息显示在浏览器的右下角,并且是透明的。