發新話題

網路管理語言 Perl 入門與實作

7.5 時間副程式
以下這個取得時間的副程式,用到的機會非常多:
引用:
# 取得時間的副程式
sub get_time {

        # 取得秒, 分, 時, 日, 月, 年
        my ($sec,$min,$hour,$day,$mon,$year)=localtime(time);

        # 月比實際少一, 所以加 1
        $mon++;

        # 判斷是否為個位數, 若是則在前面補 0
        if (length ($mon) == 1) {$mon = '0'.$mon;}
        if (length ($day) == 1) {$day = '0'.$day;}
        if (length ($hour) == 1) {$hour = '0'.$hour;}
        if (length ($min) == 1) {$min = '0'.$min;}
        if (length ($sec) == 1) {$sec = '0'.$sec;}

        # 年比實際西元年少 1900, 所以加上 1900
        $year+=1900;

        # 組合成完整的時間
        my $alltime="$year/$mon/$day $hourminsec";

}
用例:
引用:
#! /usr/bin/perl

$now = get_time();

print "$now\n";

sub get_time {
        my ($sec,$min,$hour,$day,$mon,$year)=localtime(time);
        $mon++;
        if (length ($mon) == 1) {$mon = '0'.$mon;}
        if (length ($day) == 1) {$day = '0'.$day;}
        if (length ($hour) == 1) {$hour = '0'.$hour;}
        if (length ($min) == 1) {$min = '0'.$min;}
        if (length ($sec) == 1) {$sec = '0'.$sec;}
        $year+=1900;
        my $alltime="$year/$mon/$day $hourmin:$sec";
}

TOP

8. 正規表示式
所謂正規表示式(Regular Express)是一種由字元組成的樣式,用來比對資料,看看究竟符合或不符合這個樣式,然後可做進一步的處理。比如說:電子郵件位址的樣式,可寫成: ([\w\-])+@([\w\-])+(\.[\w\-])+

8.1 樣式
正規表示式,也可以稱為是樣式(Pattern),本身自成一種小型的程式語言。由於在文件處理方面,正規表示式經常可以發揮強大的功能,因此,只要談到樣式比對,大家第一個聯想到的多半是 Perl 這個語言。可見 Perl 的樣式比對功能多麼強大。

先來看一個簡單的例子:
引用:
#! /usr/bin/perl

$str="I don't like it! John.";

if ($str =~ /like it/) {
        print "找到了!\n";
} else {
        print "沒有這個樣式!\n";
}
上例中,$str =~ /like it/ 意思是將 $str 和 "like it" 這個樣式做比對,看看是否含有該字串?(結果:有)

Perl 的正規表示式,概可分成三類:比對、置換、轉換。以下將一一說明其用法。

不過,在這之前,要先來瞭解一下,Perl 的正規表示式所定義的字元集。(這也是為什麼正規表示式被視為一種小型的程式語言的原因。)

TOP

8.2 樣式字元集
樣式是由字元集所組成的,要掌握正規表示式,首先要弄清楚字元集的定義,才能清楚地瞭解某一樣式的涵意。

以下是常用的字元集定義:
引用:
. 代表任意字元,但不包括換行字元 \n

* 代表比對成功的次數是 0 或 0 次以上

+ 代表比對成功的次數是 1 或 1 次以上

? 代表比對成功的次數是 0 或 1 次  (若用在其它數量修飾子之後,則表示 "比對採不貪心的模式")

^ 代表字串開頭

$ 代表字串結尾

\ 將其後的字元跳脫,使其回歸原字元的涵義,如:\\  , \. , \@ , \? , \*

| 樣式中的 或

( ) 群集

[0-9] 一個數字字元
[^0-9] 非數字
[a-z] 一個英文小寫字母
[^a-z] 非小寫
[A-Z] 一個英文大寫字母
[^A-Z] 非大寫
[a-zA-Z] 英文字母
[^a-zA-Z] 非英文字母

\d 同 [0-9] 數字
\D 同 [^0-9] 非數字
\w 文字, 同 [a-zA-Z0-9_]
\W 非文字,同 [^a-zA-Z0-9_]

\s 空白字元,同 [ \t\n\r\f]
\S 非空白字元,同 [^ \t\n\r\f]

\b 單字的邊界
\B 非單字的邊界

\xnn 16 進位數 nn
\nnn 8 進位數 nnn

{n} 剛好 n 次
{n, } n 次以上
{n, m} 至少 n 次,但不能超過 m 次

TOP

8.3 比對
比對的語法如下,若比對成功則傳回真,不成功則傳回假。
引用:
m/樣式/

可簡寫成 /樣式/

其中 / 可換成其它符號,但此時不能將 m 字元簡掉,如:

m!樣式!

m#樣式#

可加上修飾子:i m o s x g

用法:/樣式/修飾子

i 不計大小寫
m 視字串為多列
o 只編譯一次,以加快迴圈處理速度
s 當含有換列符號時,仍視為一列
x 允許含有註解,並忽略空白
g 全域比對


=~ 表示比對符合

!~ 表示比對不符合

$& 代表最後一次成功比對的字串

$` 代表比對到的字串之前半段所有字串
$' 代表比對到的字串之後半段所有字串
用例 1:
引用:
if ($my_best_like =~ /Perl/) {
        print "Bingo!!!\n";
} else {
        print '$%#@#$&*%$#@!', "\n";
}
若不想區分大小寫,可加上修飾子 i:
引用:
if ($my_best_like =~ /Perl/i) {
        print "Bingo!!!\n";
} else {
        print '$%#@#$&*%$#@!', "\n";
}
若想全面比對每一個地方,可加上修飾子 g:
引用:
$_ = "I want to go to San Francico. I want to!";

@word=/want/g;   # 傳回比對到的字串

print "@word\n";

輸出:

want want
註:$_ 為 m/ / 預設作用對象。

用例 2:
引用:
chomp($IP=<STDIN>);

if ($IP =~ /\d+\.\d+\.\d+\.\d+/) {
        print "$IP 可能是合法的 IP 位址!\n";
}
用例 3:將比對成功的樣式記憶起來!!! (重要功能)
引用:
chomp($IP=<STDIN>);

if ($IP =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/) {
        print "第一個 ip : $1\n";
        print "第二個 ip : $2\n";
        print "第三個 ip : $3\n";
        print "第四個 ip : $4\n";
}
用例 4:樣式中可以進行變數代換
引用:
$msg_start='^From\s.*?@?.*?\s+?\w+\s\w+\s\d+\s\d+:\d+:\d+\s\d+';

if ($line =~ /$msg_start/) {
        print "一封信件的開始!\n";
}
用例 5:樣式不符合,使用 !~ 符號
引用:
$msg_start='^From\s.*?@?.*?\s+?\w+\s\w+\s\d+\s\d+:\d+:\d+\s\d+';

# $line 若不符合 $msg_start 這個樣式
if ($line !~ /$msg_start/) {
        print "不是一封信件的開始!\n";
}
用例 6:和檔案配合
引用:
while(<DATA>) {
        print if /Kill/i;
}

__DATA__
Kill you, kill me.
Someone kill
yes do it
Just make.
Marry killed by money.
用例 7: | 的運用
引用:
while(<DATA>) {
        print if /Kill|Someone|Just/;
}

__DATA__
Kill you, kill me.
Someone kill
yes do it
Just make.
Marry killed by money.

輸出:

Kill you, kill me.
Someone kill
Just make.
用例 8:$& $` $' 的涵義
引用:
$_ = "OK! Let's go! Very happy!";

/Very/;

print '$& ==> ' . $& . "\n";
print '$` ==> ' . $` . "\n";
print '$\' ==> ' . $' . "\n";

輸出:

$& ==> Very
$` ==> OK! Let's go!
$' ==>  happy!

TOP

8.4 置換
置換是指先進行樣式比對,若有相符的地方,則將相符之處,置換成指定的字串。

置換的語法如下:
引用:
s/樣式/欲置換的字串/

可加上修飾子:e i m o s x g

i m o s x g 意思同 8.3 比對中的修飾子

e 代表將欲置換的字串視為一運算式

s/樣式/欲置換的字串/修飾子
用例 1:
引用:
# 將 $line 中的 < 符號,換成 &lt;
$line =~ s/</&lt;/;
用例 2:修飾子 i,不計大小寫
引用:
# 將 $text 中的 H1 或 h1 換成 H3
$text =~ s/H1/H3/i;
用例 3:使用記憶功能
引用:
$text =~ s/(\w+)\@(.+)/帳號:$1 主機名稱:$2/;
用例 4:刪除
引用:
$str = "I want to go to San Francico. I want to!";

$str =~ s/San//;  # 將第一個比對到的 San 字串置換掉

print $str, "\n\n";


再者:

$str = "I want to go to San Francico. I want to!";

$str =~ s/want//g;  # 將所有比對到的 want 字串置換掉

print $str, "\n\n";
用例 5:使用運算式
引用:
while(<DATA>) {
        s/7/3 + 5 * 2.1/eg;   # 因為有加 e 這個修飾子,所以 3 + 5 * 2.1 被視為運算式來執行
                          # 它會將找到的 7,用 3 + 5 * 2.1 的運算結果來取代
}

__DATA__
Marry 6
John 7
Kenny 8


輸出:

Marry 6
John 13.5
Kenny 8


以下是 CGI 程式中經常用的解碼程式片段:

$value=~ s/%(..)/pack("c",hex($1))/ge;

因為有加 e 這個修飾子,所以 pack("c",hex($1)) 被視為運算式來執行

TOP

8.5 轉換
轉換可以做字元的變換或刪除字元的動作。

語法如下:
引用:
tr/字元集/欲轉換的字元集/
y/字元集/欲轉換的字元集/

可再加上修飾子:c d s

d 刪除字元
c 將不在指定字元集中的字元(包括換行字元),換成欲轉換的字元集
s 將重覆字元刪除
用例 1:小寫換成大寫
引用:
$text =~ tr/a-z/A-Z/;
用例 2:刪除空白字元
引用:
$text="1 abc 23 PID";

$text =~ tr/ //d;

print $text, "\n\n";

輸出:

1abc23PID
用例 3:壓縮重覆的字元 (使用修飾子 s)
引用:
$text = 'goodyesMMMllnnnn';
$text =~ tr/a-zA-Z//s;

print $text;

# 輸出結果:

godyesMln

重覆的字元只剩一個。
用例 4:修飾子 c
引用:
$text="1 abc 23 PID";

$text =~ tr/[0-9]/*/c;  # 將非數字字元換成 * 號

print $text, "\n\n";

輸出:

1*****23****

TOP

9. 參考
什麼是參考(reference)?

所謂 "參考" 是指:一個純量變數,內含另一個變數的位址。在 Perl 中,稱此種參考為硬參考(Hard Reference)。

參考是 Perl 架構複雜資料結構的基石,在增進副程式傳值效率方面也有大用,更是 Perl 運用物件導向技術時重要的依靠。因此瞭解參考,是踏入 Perl 進階層級的第一步。參考的運算子為 \ 這個符號,只要在變前前加上 \ 即可。


9.1 常見的參考
Perl 常見的參考有以下幾種:

1. 純量參考:
引用:
$num=56;

# $scalar_ref 內含 $num 的位址
$scalar_ref = \$num;

# 只要在參考之前加上 $ ,即可取得原參考對象的內含值(即 56)
print $$scalar_ref;
2. 陣列參考:
引用:
@total=(1,2,4);

$array_ref = \@total;

# 只要在參考之前加上 @ ,即可取得原參考對象,即 @total
print @$array_ref;
3. 雜湊參考:
引用:
%all=(
        mmm => "KKK",
        nnn => "MMM"
);

$hash_ref = \%all;

# hash 參考可以利用 -> 來取得其鍵/值
print $hash_ref->{mmm};

# 加上 % 可以取得原雜湊

@keys = keys %$hash_ref;
4. 副程式參考:
引用:
sub max {
        my ($a, $b) = @_;

        ($a > $b) ? $a : $b;
}

# $sub_ref 為 &max 副程式的參考
$sub_ref = \&max;

# 加上 & 即可呼叫該副程式
$max = &$sub_ref(5, 18);

print $max;
5. 檔案代碼參考(glob reference):
引用:
sub write_it {

        my $file= shift;

        print $file "test .....\n";

}

open(FHD, "> test.log") || die "$!\n";

# 將檔案代碼 FHD 傳入 write_it 副程式中
write_it(\*FHD);

close(FHD);

TOP

9.2 副程式傳參考
許多情況下,副程式或函式需要傳遞參考進去,比如:File::Find 模組中的 find 這個方法:
引用:
#! /usr/bin/perl

use File::Find;
$index=1;

# 路徑設定
my $dir=shift || '/home/ols3';

my $tmp="dirlist.txt";

# 開啟記錄暫存檔
open(W, "> $tmp") || die "$!\n";

# 走訪該目錄,注意!!! 此處傳入一個回呼副程式 doit 的參考:\&doit
find(\&doit, $dir);

close(W);


# 動作區
sub doit {
        print_process_status($index);
        print W "$File::Find::name\n";
        $index++;
}

sub print_process_status {
    my $i=shift;
    my $j = $i % 4;
    SWITCH : {
        $j == 0 && do { print STDERR " (|)\r";  last SWITCH; };
        $j == 1 && do { print STDERR " (/)\r";  last SWITCH; };
        $j == 2 && do { print STDERR " (-)\r";  last SWITCH; };
        $j == 3 && do { print STDERR " (\\)\r"; last SWITCH; };
    }
}

TOP

10. 模組
之前曾提到:Perl 自第 5 版之後,支援物件導向設計,具模組功能。Perl 的模組簡明易用,而且 Perl 的社群非常活躍,產量豐富,幾年下來,累聚非常龐大的模組程式庫,我們稱之為 CPAN (Comprehensive Perl Archive Network)。因為 Perl 模組實在是一個大寶庫,所以我們在這章中將簡單介紹一下模組的安裝流程。

10.1 安裝模組
方法一:手動自行設定安裝

以安裝 DBI 為例
引用:
ncftp ftp2.tnc.edu.tw
cd /pub/unix/perl/CPAN/modules/by-module/
cd DBI
get DBI-1.37.tar.gz
quit

tar xvzf DBI-1.37.tar.gz
cd DBI-1.37

# 設定
perl Makefile.PL

# 編譯
make

# 測試
make test

# 安裝
make install
若欲安裝其它模組,方法類同。請在解壓模組之後,務必詳看 README 的說明。

方法二:自動設定安裝

採用 CPAN 安裝介面,用法如下:
引用:
1. 切換成 root:su -

2. 執行

perl -MCPAN -e shell

以進入 CPAN 的交談介面中,

第一次執行時,會詢問您一些相關設定問題,請按您的環境來回答,
大部份部問題只要按 Enter 即可。

初始化的設定結果,它會寫在  CPAN 的 Config.pm 中,

可能的路徑例子如下:

/usr/local/lib/perl5/5.8.0/CPAN/Config.pm

但您的平台未必我的一樣,請勿直接套用。

若您要改變欲 CPAN 的站台,可修改 Config.pm 中的 'urllist',

例如:'urllist' => [q[訪客無法瀏覽此圖片或連結,請先 註冊登入會員 ]],

可將抓檔的站台設為敝中心 FTP2 的 CPAN。


3. 安裝

在提示符號下,執行 install DBI:

cpan> install DBI

它會幫你自動完成設定安裝。

TOP

10.2 使用模組
模組裝好了之後,如何使用呢?

很簡單! 只要在您的 Perl 程式中加上 use 模組; 即可,如下所示:
引用:
#! /usr/bin/perl

use DBI;  # 宣告使用 DBI 模組內的所有方法

my $db="test";
my $host='localhost';
my $user='root';
my $password='ppp123';

........
........

TOP

發新話題

本站所有圖文均屬網友發表,僅代表作者的觀點與本站無關,如有侵權請通知版主會盡快刪除。