久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

perl基本語(yǔ)法

 hundouluo 2011-02-18

最近在研究 openSUSE 的 OBS (編譯系統(tǒng)),其中很多部分用到 Perl,。而且自己也感到有必要學(xué)點(diǎn) Perl,,當(dāng)有一點(diǎn)其他程序語(yǔ)言的基礎(chǔ),,再學(xué)一門(mén)語(yǔ)言,入門(mén)還是非常簡(jiǎn)單的,。Perl 在 GNU/Linux 上應(yīng)用如此廣泛,,很多地方替換 shell 腳本會(huì)更靈活優(yōu)秀高效,學(xué)習(xí)它也很有必要,。本文是學(xué)習(xí)時(shí)的筆記,,多是語(yǔ)法使用示例,,沒(méi)有什么說(shuō)明,。擬研究 OBS 時(shí),依據(jù)某個(gè)應(yīng)用再寫(xiě)一篇 Perl 應(yīng)用教程,。

標(biāo)量
數(shù)字
字符串
數(shù)字和字符串之間的自動(dòng)轉(zhuǎn)換
Perl 內(nèi)嵌的警告
標(biāo)量變量
print 輸出
if 控制結(jié)構(gòu)
Boolean 值
用戶(hù)的輸入 <STDIN>
chomp 操作
while 控制結(jié)構(gòu)
undef 值
defined 函數(shù)
列表和數(shù)組
qw 簡(jiǎn)寫(xiě)
列表賦值
pop 和 push 操作
shift 和 unshift 操作
字符串中引用數(shù)組
foreach 控制結(jié)構(gòu)
最常用的默認(rèn)變量 : $_
reverse 操作
sort 操作
標(biāo)量和列表上下文
子程序
使用 sub 定義子程序
調(diào)用子程序
參數(shù)
my 變量
使用 strict Pragma
省略 &
輸入和輸出
從標(biāo)準(zhǔn)輸入設(shè)備輸入
從 <> 輸入
調(diào)用參數(shù)
輸出到標(biāo)準(zhǔn)輸出設(shè)備
使用 printf 格式化輸出
數(shù)組和 printf
句柄 (即文件描述符)
文件句柄的打開(kāi)
Bad 文件句柄
關(guān)閉文件句柄
嚴(yán)重錯(cuò)誤和 die
使用文件句柄
哈希
什么是哈希
哈希元素的存取
哈希函數(shù)
正則表達(dá)式
簡(jiǎn)單的模式
正則表達(dá)式的應(yīng)用
使用 m// 匹配
可選的修飾符
錨定
匹配變量
使用正則表達(dá)式處理文件
使用 s/// 進(jìn)行替換
split 操作
join 函數(shù)
列表上下文中的 m//
更強(qiáng)大的正則表達(dá)式
更多控制結(jié)構(gòu)
unless 控制結(jié)構(gòu)
until 控制結(jié)構(gòu)
表達(dá)式修飾符
The Naked Block 控制結(jié)構(gòu)
elsif 語(yǔ)句
自增和自減 (同C)
for 控制結(jié)構(gòu) (同C)
循環(huán)控制
邏輯操作符 && 和 ||
文件校驗(yàn)
文件檢測(cè)操作
stat 和 lstat 函數(shù)
localtime 函數(shù)
位操作
目錄操作
在目錄樹(shù)上移動(dòng)
Globbing
Globbing 的替換語(yǔ)法
目錄句柄
刪除文件 unlink
重命名文件
鏈接文件
創(chuàng)建和刪除目錄
修改權(quán)限
改變所有者
改變時(shí)間戳
字符串和排序
使用索引尋找子串
使用 substr 操作子串
使用 sprintf 格式化數(shù)據(jù)
進(jìn)程管理
system 函數(shù)
exec 函數(shù)
環(huán)境變量
使用反引號(hào)得到輸出
像文件句柄一樣處理進(jìn)程
fork 函數(shù)
發(fā)送和接受信號(hào)
Perl 模塊
查找
安裝模塊
使用簡(jiǎn)單的模塊
一些高級(jí)的 Perl 技術(shù)
利用 eval 捕捉錯(cuò)誤

標(biāo)量

標(biāo)量是 Perl 中最簡(jiǎn)單的數(shù)據(jù)類(lèi)型,。大多數(shù)的標(biāo)量是數(shù)字(如 255 或 3.25e20)或者字符串(如 hello或者蓋茨堡地址)。

數(shù)字

perl中所有數(shù)字內(nèi)部的格式都是雙精度浮點(diǎn)數(shù),。

浮點(diǎn)數(shù)

1.25
255.000
255.0
7.25e45 #7.25x10 的 45 次方(一個(gè)大整數(shù))
-6.5e24 # -6.5x10 的 24 次方(一個(gè)大的負(fù)數(shù))
-12e-24 #- -12x10 的-24 次方(很小的負(fù)數(shù))
-1.2E-23 #指數(shù)符號(hào)可以大寫(xiě)(E)

整數(shù)

0
2001
-40
255
61298040283768

其中 61298040283768 也可以寫(xiě)作:

61_298_040_283_768

非十進(jìn)制整數(shù)

0377     #八進(jìn)制數(shù)字 377,等同于十進(jìn)制數(shù)字 255
0xff       #十六進(jìn)制數(shù)字 FF,等同于十進(jìn)制數(shù)字 255
0b11111111 #等同于十進(jìn)制數(shù)字 255

可以用下劃線(xiàn)表示:

0x1377_0B77
0x50_65_72_7C

數(shù)字操作符

2+3       #2+3,5
5.1-2.4  #5.1-2.4,2.7
3*12     #3*12,36
14/2      #14/2,7
10.2/0.3  #10.2/0.3,34
10/3      #通常是浮點(diǎn)除,3.33333... ...

字符串

單引號(hào)字符串

'fred' #四個(gè)字符:f,r,e,d
'' #空字符(沒(méi)有字符)
'hello\n'
'\'\\' #單引號(hào)(')跟著反斜線(xiàn)(\)字符串

單引號(hào)中的 "\n" 不會(huì)被當(dāng)作換行符來(lái)處理,。

雙引號(hào)字符串

"barney"         #等同于 'barney'
"hello world\n"  #hello world,換行

字符串操作符

鏈接操作符 "."
"hello"."world"     # 同于 "helloworld"
"hello".''."world"  # 同于 "hello world"
'hello world'."\n"  # 同于 "hello world\n"
重復(fù)操作符 "x"
"fred" x 3   # "fredfredfred"
5 x 4        # 等于 "5" x 4, "5555"

數(shù)字和字符串之間的自動(dòng)轉(zhuǎn)換

大多數(shù)情況下,Perl 將在需要的時(shí)候自動(dòng)在數(shù)字和字符串之間轉(zhuǎn)換。它怎樣知道什么時(shí)候需要字符串,什么時(shí)候需要數(shù)字呢?這完全依賴(lài)于標(biāo)量值之間的的操作符,。如果操作符(如+)需要數(shù)字,Perl 將把操作數(shù)當(dāng)作數(shù)字看待,。如果操作符需要字符串(如 . ), Perl 將把操作數(shù)當(dāng)作字符串看待。不必?fù)?dān)心數(shù)字和字符串的區(qū)別;使用恰當(dāng)?shù)牟僮鞣?Perl 將為你做剩下的事,。

"12" * "3"  # * 操作符需要數(shù)字,所以結(jié)果為 36
"12fred34" * " 3" # 結(jié)果仍然是 36 , 后面的非數(shù)字部分和前面的空格都過(guò)濾掉,。
"Z" . 5 * 7 # 等于 "Z".35,, 或 "Z35"

Perl 內(nèi)嵌的警告

使用 -w 參數(shù)可以打開(kāi)警告:

$ perl -w perl程序   # 命令行執(zhí)行警告
#!/usr/bin/perl -w  # 源代碼中使用警告

標(biāo)量變量

標(biāo)量變量可以存放一個(gè)標(biāo)量值。標(biāo)量變量的名字由一個(gè)美圓符號(hào)($)后接 Perl 標(biāo)識(shí)符:由字母或下劃線(xiàn)開(kāi)頭,后接字母,數(shù)字,或者下劃線(xiàn),?;蛘哒f(shuō)由字母,數(shù)字和下劃線(xiàn)組成,但不能由數(shù)字開(kāi)頭。大小寫(xiě)是嚴(yán)格區(qū)分的:變量$Fred 和變量$fred是不同的,。任意字母,數(shù)字,下劃線(xiàn)都有意義,如:

$a_very_long_variable_that_ends_in_1
$a_very_long_variable_that_ends_in_2

標(biāo)量賦值

$fred = 17;
$barney = "hello";
$barney = $fred + 3;# 將$fred 的值加上三賦給$barney (20)
$barney= $barney*2;#將變量$barney 乘 2 再賦給$barney (40)

二元賦值操作符

$fred = $fred + 5; #沒(méi)有用二元賦值操作符
$fred+=5;          #利用二元賦值操作符
$barney = $barney*3;
$barney*=3;
$str = str . ""; #$str 后接空格;
$str .= "";    #同上

print 輸出

print "hello world\n";   #輸出 hello world,后接換行符
print "The answer is", 6*7, ".\n"

字符串中引用標(biāo)量變量

$meal = "brontosaurus steak" ;
$barney = "fred ate a $meal";
$barney = 'fred ate a'.$meal;    # 同上

if 控制結(jié)構(gòu)

if ($name gt 'fred') {
print "$name’comes after 'fred' in sorted order.\n";
}

Boolean 值

perl 沒(méi)有專(zhuān)門(mén)的 Boolean 值,, 真假值這樣判斷:

  • 如果值為數(shù)字,0 是 false;其余為真
  • 如果值為字符串,則空串(‘)為 false;其余為真
  • 如果值的類(lèi)型既不是數(shù)字又不是字符串,則將其轉(zhuǎn)換為數(shù)字或字符串后再利用上述規(guī)則

這些規(guī)則中有一個(gè)特殊的地方。由于字符串'0' 和數(shù)字 0 有相同的標(biāo)量值,Perl 將它們相同看待,。也就是說(shuō)字符串 '0' 是唯一一個(gè)非空但值為 0 的串,。

用戶(hù)的輸入 <STDIN>

chomp 操作

$text = "a line of text\n";    # 也可以由<STDIN>輸入
chomp($text);                 #去掉換行符(\n)。

一步執(zhí)行:

chomp ($text = <STDIN>); #讀入,但不含換行符

chomp 是一個(gè)函數(shù),。作為一個(gè)函數(shù),它有一個(gè)返回值,為移除的字符的個(gè)數(shù),。這個(gè)數(shù)字基本上沒(méi)什么用:

$food = <STDIN>;
$betty = chomp $food; #得到值 1

如上,在使用 chomp 時(shí),可以使用或不使用括號(hào)()。這又是 Perl 中的一條通用規(guī)則:除非移除它們時(shí)含義會(huì)變,否則括號(hào)是可以省略的,。

while 控制結(jié)構(gòu)

$count = 0;
while ($count < 10) {
$count + = 2;
print "count is now $count\n";
}

undef 值

變量被賦值之前使用它會(huì)有什么情況發(fā)生呢?通常不會(huì)有什么嚴(yán)重的后果,。變量在第一次賦值前有一個(gè)特殊值 undef, 按照 Perl 來(lái)說(shuō)就是:"這里什么也沒(méi)有,請(qǐng)繼續(xù)"。如果這里的“什么也沒(méi)有”是一些“數(shù)字”,則表現(xiàn)為 0,。如果是“字符串”,則表現(xiàn)為空串,。但 undef 既非數(shù)字也非字符串,它是另一種標(biāo)量類(lèi)型,。

defined 函數(shù)

能返回 undef 的操作之一是行輸入操作,<STDIN>。通常,它會(huì)返回文本中的一行,。但如果沒(méi)有更多的輸入,如到了文件的結(jié)尾,則返回 undef,。要分辨其是 undef 還是空串,可以使用 defined 函數(shù), ,如果其參數(shù)是 undef 值就返回 false,,其他值返回 true,。

$madonna = <STDIN>;
If ($defined ($madonna)){
print "The input was $madonna";
} else {
print "No input available!\n;
}

如果想聲明自己的 undef 值,可以使用 undef:

$madonna = undef ; #同$madonna 從未被初始化一樣。

列表和數(shù)組

#!/usr/bin/env perl -w
$fred[0] = "yabba";
$fred[1] = "dabba";
$fred[2] = "doo";
print @fred;
#print @fred."\n";

qw 簡(jiǎn)寫(xiě)

qw ! fred barney betty wilma dino !
qw#  fred barney betty wilma dino # #有些像注釋
qw(   fred barney betty wilma dino )
...

列表賦值

($fred, $barney, $dino) = ("flintstone", "rubble", undef);
($fred, $barney) = qw <flintstone rubble slate granite>; #兩個(gè)值被忽略了
($rocks[0],$rocks[1],$rocks[2],$rocks[3]) = qw/talc mica feldspar quartz/;

當(dāng)想引用這個(gè)數(shù)組時(shí), Perl 有一種簡(jiǎn)單的寫(xiě)法,。在數(shù)組名前加@(后沒(méi)有中括號(hào)) 來(lái)引用整個(gè)數(shù)組,。 你可以把他讀作 "all of the "(所有的)”,所以@rocks 可以讀作 "all of the rocks(所有的石頭)"。其在賦值運(yùn)算符左右均有效:

@rocks = qw / bedrock slate lava /;
@tiny = ();                         #空表
@giant = 1..1e5;               #包含 100,000 個(gè)元素的表
@stuff = (@giant, undef, @giant);      #包含 200,001 個(gè)元素的表
@dino = "granite";
@quarry = (@rocks, "crushed rock", @tiny, $dino);

pop 和 push 操作

@array = 5..9;
$fred = pop(@array);      #$fred 得到 9,@array 現(xiàn)在為(5,6,7,8)
$barney = pop @array;   #$barney gets 8, @array 現(xiàn)在為(5,6,7)
pop @array;                   #@array 現(xiàn)在為(5,6)(7 被丟棄了)
push(@array,0);                   #@array 現(xiàn)在為(5,6,0)
push @array,8;                    #@array 現(xiàn)在為(5,6,0,8)
push @array,1..10;              #@array 現(xiàn)在多了 10 個(gè)元素
@others =qw/9 0 2 1 0 /;
push @array,@others;          #@array 現(xiàn)在又多了 5 個(gè)元素(共有 19 個(gè))

shift 和 unshift 操作

push 和 pop 對(duì)數(shù)組的末尾進(jìn)行操作(或者說(shuō)數(shù)組右邊有最大下標(biāo)的元素,這依賴(lài)于你是怎樣思考的),。相應(yīng)的, unshift 和 shift 對(duì)一個(gè)數(shù)組的開(kāi)頭進(jìn)行操作(數(shù)組的左端有最小下標(biāo)的元素) ,。下面是一些例子:

@array = qw# dino fred barney #;
$m = shift (@array);       #$m 得到 "dino", @array 現(xiàn)在為 ("fred", "barney")
$n = shift @array;          #$n 得到 "fred", @array 現(xiàn)在為 ("barney")
shift @array;                  #@array 現(xiàn)在為空
$o = shift @array;          #$o 得到 undef, @arry 仍為空
unshift(@array,5);          #@array 現(xiàn)在為(5)
unshift @array,4;           #@array 現(xiàn)在為(4,5)
@others = 1..3;
unshift @array, @others;  #array 現(xiàn)在為(1,2,3,4,5)

和 pop 類(lèi)似,如果其數(shù)組變量為空,則返回 undef,。

字符串中引用數(shù)組

和標(biāo)量類(lèi)似,數(shù)組也可以插入雙引號(hào)的字符串中,。插入的數(shù)組元素會(huì)自動(dòng)由空格分開(kāi):

@rocks = qw{ flintstone slate rubble };
print "quartz @rocks limestone\n";        #輸出為 5 種 rocks 由空格分開(kāi)

foreach 控制結(jié)構(gòu)

foreach $rock (qw/ bedrock slate lava /) {
print "One rock is $rock.\n" ;           #打印出 3 種 rocks
}

這里的$rock不是這些列表元素中的一個(gè)拷貝而是這些元素本身

最常用的默認(rèn)變量 : $_

如果在 foreach 循環(huán)中省略了控制變量,那 Perl 會(huì)使用其默認(rèn)的變量:$_。除了其不尋常的名字外,這和普通變量類(lèi)似,如下面代碼所示:

foreach(1..10){                 #使用默認(rèn)的變量$_
print "I can count to $_!\n";
}
$_ = "Yabba dabba doo\n";
print;                                      # 打印出默認(rèn)變量 $_

reverse 操作

reverse(逆轉(zhuǎn))操作將輸入的一串列表(可能是數(shù)組)按相反的順序返回,。

@fred = 6 .. 10;
@barney = reverse (@fred);  #得到 10,9,8,7,6
@wilma = reverse 6 . .10;   #同上,沒(méi)有使用額外的數(shù)組
@fred = reverse @fred;     #將逆轉(zhuǎn)過(guò)的字符串存回去

sort 操作

@rocks = qw/ bedrock slate rubble granite /;
@sorted = sort(@rocks);                      #得到 bedrock, granite, rubble, slate

標(biāo)量和列表上下文

42 + something               #something 必須是標(biāo)量
sort something                #something 必須是列表
@people = qw( fred barney betty );
@sorted = sort @people;            #列表內(nèi)容: barney , betty, fred
$number = 42 + @people;            #標(biāo)量?jī)?nèi)容:42+3,得到 45

另一個(gè)例子是 reverse,。在列表 context 中,它返回反轉(zhuǎn)的列表。在標(biāo)量 context 中,返回反轉(zhuǎn)的字符串(或者將反轉(zhuǎn)的結(jié)果串成一個(gè)字符串):

@backwards = reverse qw / yabba dabba doo /;
#返回 doo, dabba, yabba
$backwards = reverse qw/ yabba  dabba doo /;
#返回 oodabbadabbay

在列表 Context 中使用 Scalar-Producing 表達(dá)式

如果一個(gè)表達(dá)式不是列表值,則標(biāo)量值自動(dòng)轉(zhuǎn)換為一個(gè)元素的列表:

@fred = 6*7;
@barney = "hello" . '' . "world";

強(qiáng)制轉(zhuǎn)換為標(biāo)量 Context

偶爾,你可能需要標(biāo)量 context 而 Perl 期望的是列表,。這種情況下,可以使用函數(shù) scalar,。它不是一個(gè)真實(shí)的函數(shù)因?yàn)槠鋬H是告訴 Perl 提供一個(gè)標(biāo)量 context:

@rocks = qw(talc quartz jade obsidian);
print "How many rocks do you have?\n;
print "I have " @rocks, "rocks!\n";    # 錯(cuò)誤,輸出 rocks 的名字
print "I have " scalar @rocks, "rocks!\n;    # 正確,輸出其數(shù)字

<STDIN> 在列表 Context 中

@lines = <STDIN>; #將輸入讀入列表 context 中
chomp (@lines = <STDIN>); #讀入所有的行,不包括換行符

子程序

使用 sub 定義子程序

sub marine {
$n + = 1; #全局變量$n
print "Hello, sailor number $n!\n";
}

調(diào)用子程序

&marine; #輸出 Hello, sailor number 1!
&marine; #輸出 Hello, sailor number 2!
&marine; #輸出 Hello, sailor number 3!
&marine; #輸出 Hello, sailor number 4!

通常有括號(hào),即便參數(shù)為空。子程序?qū)⒗^承調(diào)用者的 @_ 的值,。

參數(shù)

$n = &max(10,15);     # 此子程序有 2 個(gè)參數(shù)

此參數(shù)列表被傳到子程序中;這些參數(shù)可以被子程序使用,。當(dāng)然,這些參存放在某個(gè)地方,在 Perl 中,會(huì)自動(dòng)將此參數(shù)列表(此參數(shù)列表的另一個(gè)名字)自動(dòng)存放在一個(gè)叫做@_的數(shù)組中。子程序可以訪(fǎng)問(wèn)次數(shù)組變量來(lái)確定此參數(shù)的個(gè)數(shù)以及其值,。這也就是說(shuō)此子程序參數(shù)的第一個(gè)值存放在$_[0]中,第二個(gè)存放在$_1,依次類(lèi)推,。但必須強(qiáng)調(diào)的是這些變量和 $_ 這個(gè)變量沒(méi)有任何關(guān)系,如$dino3(數(shù)組 @dino 的一個(gè)元素)和$dino 的關(guān)系一樣。這些參數(shù)必須存放在某個(gè)數(shù)組變量中, Perl 存放在@_這個(gè)變量中,。

 sub max{
if($_[0] > $_[1]) {
$_[0];
} else {
$_[1];
}
}

my 變量

foreach (1..10){
my($square) = $_*$_; #本循環(huán)中的私有變量
print "$_ squared is $squrare.\n";
}

變量$square 是私有的,僅在此塊中可見(jiàn);在本例中,此塊為 foreach 循環(huán)塊,。

當(dāng)然,my 操作不會(huì)改變賦值參數(shù)的 context:

my ($num) = @_;         # 列表 context, 同($sum) = @_;
my $num = @_;          # 標(biāo)量 context,同$num = @_;

使用 strict Pragma

use strict; #迫使采用更嚴(yán)格的檢測(cè)

省略 &

有些地方調(diào)用子程序可以不要 &

my @cards = shuffle(@deck_of_cards); # &是不必要的

輸入和輸出

從標(biāo)準(zhǔn)輸入設(shè)備輸入

從標(biāo)準(zhǔn)輸入設(shè)備輸入是容易的。使用<STDIN>,。在標(biāo)量 context 中它將返回輸入的下一行:

$line = <STDIN>;     #讀入下一行;
chomp($line);        #去掉結(jié)尾的換行符
chomp($line=<STDIN>)  #同上,更常用的方法

于,行輸入操作在到達(dá)文件的結(jié)尾時(shí)將返回 undef,這對(duì)于從循環(huán)退出時(shí)非常方便的:

while (defined($line = <STDIN>)) {
print "I saw $line";
}

從 <> 輸入

尖括號(hào)操作(<>)是一種特殊的行輸入操作,。其輸入可由用戶(hù)選擇

$n = 0;
while (defined($line = <>)) {
$n += 1;
chomp($line);
print "$n  $line\n";
}
while (<>) {
chomp;
print "It was $_ that I saw!\n";
}

調(diào)用參數(shù)

技術(shù)上講,<>從數(shù)組@ARGV 中得到調(diào)用參數(shù),。這個(gè)數(shù)組是 Perl 中的一個(gè)特殊數(shù)組,其包含調(diào)用參數(shù)的列表,。 換句話(huà)說(shuō),這和一般數(shù)組沒(méi)什么兩樣 (除了其名字有些特別: 全為大寫(xiě)字母) ,程序開(kāi)始運(yùn)行時(shí),調(diào)用參數(shù)已被存在@ARGV 之中了。

輸出到標(biāo)準(zhǔn)輸出設(shè)備

print @array;      #打印出元素的列表
print "@array";    #打印一個(gè)字符串(包含一個(gè)內(nèi)插的數(shù)組)

第一個(gè)語(yǔ)句打印出所有的元素,一個(gè)接著一個(gè),其中沒(méi)有空格,。第二個(gè)打印出一個(gè)元素,它為@array 的所有元素,其被存在一個(gè)字符串中,。也就是說(shuō),打印出@array 的所有元素,并由空格分開(kāi)。如果@array 包含 qw /fred barney betty /,則第一個(gè)例子輸出為:fredbarneybetty,而第二個(gè)例子輸出為 fred barney betty(由空格分開(kāi)),。

使用 printf 格式化輸出

printf "Hello, %s :  your password expires in %d days!\n",
$user, $days_to_die;
printf "%6f\n" 42;          # 輸出為 ○○○○ 42 (○此處指代空格)
printf "%23\n",2e3+1.95;  # 2001

數(shù)組和 printf

my @items = qw( wilma dino pebbles );
my $format = "The items are:\n". ("%10s\n" x @items);
printf $format, @items;

等同:

printf "The items are:\n". ("%10s\n"x @items), @items;

本處 @items 有兩個(gè)不同的 context (上下文),,第一次表示元素個(gè)數(shù),第二次表示列表中的所有元素,。

句柄 (即文件描述符)

Perl 自身有六個(gè)文件句柄 : STDIN,STDOUT,STDERR,DATA,ARGV,ARGVOUT

文件句柄的打開(kāi)

open CONFIG, "dino" ;
open CONFIG, "<dino"    ;
open BEDROCK, ">fred"   ;
open LOG, ">>logfile" ;

Perl 的新版本中(從 Perl5.6 開(kāi)始),,open 支持“3 參數(shù)”類(lèi)型:

open CONFIG, "<",  "dino";
open BEDROCK, ">", $file_name;
open LOG, ">>", &logfile_name();

Bad 文件句柄

關(guān)閉文件句柄

close BEDROCK;

嚴(yán)重錯(cuò)誤和 die

可以和 C 中使用 perror 類(lèi)似,用 die 函數(shù):

if (!open LOG, ">>logfile") {
die "Cannot create logfile:$!";
}

使用文件句柄

if (!open PASSWD, "/etc/passwd") {
die "How did you get logged in?($!)";
}
while (<PASSWD>) {
chomp;
...
}

哈希

什么是哈希

和 Python 的字典一樣

哈希元素的存取

$hash {$some_key}

作為整體的 hash

要引用整個(gè) hash,使用百分號(hào)(“%” )作為前綴,。

%some_hash = ("foo",35, "bar", 12.4, 2.5, "hello", "wilma", 1.72e30, "betty", "bye\n");

hash 的值(在列表 context 中)是一個(gè) key/value 對(duì)的列表 :

@array_array = %some_hash;

哈希賦值

%new_hash = %old_hash;
%inverse_hash = reverse %any_hash;

大箭頭符號(hào) (=>)

my %last_name = (
"fred” => "flintstone",
"dino" => undef,
"barney" => "rubble",
"betty" => "rubble",
);

哈希函數(shù)

keys 和 values

my %hash = ("a" => 1, "b" => 2, "c" => 3);
my @k = keys %hash;
my @v = values %hash;

each 函數(shù)

while (($key, $value) = each %hash) {
print "$key => $value\n";
}

exists 函數(shù)

if (exists $books{$dino}) {
print "Hey, there's a libaray card for dino!\n";
}

delete 函數(shù)

my $person = "betty";
delete $books{$person};   # 將$person 的借書(shū)卡刪除掉

正則表達(dá)式

簡(jiǎn)單的模式

$_ = "yabba dabba doo";
if (/abba/) {
print "It matched!\n";
}

所有在雙引號(hào)中的轉(zhuǎn)義字符在模式中均有效,因此你可以使用 /coke\tsprite/ 來(lái)匹配 11 個(gè)字符的字符串 coke, tab(制表符),sprite,。

元字符

.
?
+
*

模式中的分組

/fred+/      # 只能匹配 fredddddd 等
/(fred)+/    # 能匹配  fredfredfred 等
/(fred)*/    # 可以匹配 "hello,world", 因?yàn)?* 是匹配前面的 0或多次

選擇符 (|)

/fred|barney|betty/
/fred( |\t)+barney/

字符類(lèi)

指 [] 中的一列字符,。

字符類(lèi)的簡(jiǎn)寫(xiě)
\d    ==   [0-9]
\w    ==   [A-Za-z0-9_]
\s    ==   [\f\t\n\r]  # 格式符(form-feed),、制表符(tab)、換行符,、回車(chē)
簡(jiǎn)寫(xiě)形式的補(bǔ)集
\D  == [^\d]
\W  ==  [^\w]
\S  ==  [^\s]

可以組合:

[\d\D]   # 任何數(shù)字和任何非數(shù)字,,可以匹配所有字符!比如 . 是不能匹配所有字符的
[^\d\D]   # 無(wú)用

正則表達(dá)式的應(yīng)用

使用 m// 匹配

同 qw // 一樣,,可以使用任何成對(duì)字符,,比如可以使用 m(fred), m<fred>, m{fred}, m[fred],或者 m,fred,, m!fred!, m^fred^。

如果使用 / 作為分隔符,,可以省略前面的 m

如果使用配對(duì)的分隔符, 那不用當(dāng)心模式內(nèi)部會(huì)出現(xiàn)這些分隔符, 因?yàn)橥ǔDJ絻?nèi)部的分隔符也是配對(duì)的,。 因此, m(fred(.*)barney), m{\w{2,}}, m[wilma[\n \t]+betty]是正確的。對(duì)于尖括號(hào)(<和>),它們通常不是配對(duì)的,。如模式 m{(\d+)\s*>=?\s*(\d+)},如果使用尖括號(hào),模式中的尖括號(hào)前因當(dāng)使用反斜線(xiàn)(\), 以免模式被過(guò)早的結(jié)束掉。

可選的修飾符

不區(qū)分大小寫(xiě): /i

if (/yes/i) {            #大小寫(xiě)無(wú)關(guān)
print "In that case, I recommend that you go bowling.\n";
}

匹配任何字符: /s

使用/s 這個(gè)修飾符,,它將模式中點(diǎn) (.) 的行為變成同字符類(lèi) [\d\D] 的行為類(lèi)似:可以匹配任何字符,包括換行符,。從下例中可見(jiàn)其區(qū)別:

$_ = "I saw Barney\ndown at the bowing alley\nwith Fred\nlast night.\n;
if (/Barney.*Fred/s) {
print "That string mentions Fred after Barney!\n";
}

添加空格: /x

/x 修飾符,允許你在模式中加入任何數(shù)量的空白,以方便閱讀:

/-?\d+\.?\d*/        # 這是什么含義?
/ -? \d+ \.? \d* /x  # 要好些

Perl 中,注釋可以被作為空白,因此使用/x,可以在模式中加上注釋?zhuān)?/p>

/
-?  #可選的負(fù)號(hào)
d+ #小數(shù)點(diǎn)前一個(gè)或多個(gè)十進(jìn)制數(shù)字
\.? #可選的小數(shù)點(diǎn)
\d* #小數(shù)點(diǎn)后一些可選的十進(jìn)制數(shù)字
/x #模式結(jié)束

使用多個(gè)修飾符

if (/barney.*fred/is/){ # /i 和/s
print "That string mentions Fred after Barney!\n";
}

錨定

^  開(kāi)頭
$  結(jié)尾

注意:/^fred$/能同時(shí)匹配上 "fred" 和 "fred\n"。

/^\s*$/   # 匹配空行

詞錨定: \b

/\bfred\b/ 可以匹配單詞 "fred", 但不能匹配 "frederick"

綁定操作符: =~

對(duì) $_ 進(jìn)行匹配只是默認(rèn)的行為, 使用綁定操作符 ( =~ ) 將告訴 Perl 將右邊的模式在左邊的字符串上進(jìn)行匹配,而非對(duì) $_ 匹配,。

my $some_other = "I dream of betty rubble.";
if ($some_other =~ /\brub/) {
print "Aye, there's the rub.\n";
}

綁定操作符優(yōu)先級(jí)較高:

my $likes_perl = <STDIN> =~ /\byes\b/i;

匹配變量

$_ = "Hello there, neighbor";
if (/\s(\w+),/) {              #空格和逗號(hào)之間的詞
print "The word was $1\n";
}

自動(dòng)匹配變量

$&    # 整個(gè)被匹配的部分
$`     # 匹配部分的前一部分存放在$`之中
$'     # 后一部分被存到$'

使用正則表達(dá)式處理文件

使用 s/// 進(jìn)行替換

$_ = "He's out bowling with Barney tonight.";
s/Barney/Fred/;               # Barney 被 Fred 替換掉
print "$_\n";
#接上例:現(xiàn)在 $_ 為 "He's out bowling with Fred tonight."
s/Wilma/Betty/;              # 用 Wilma 替換 Betty(失敗)
s/with (\w+)/agaist $1's team/;
print "$_\n";                  # 為 "He's out bowling against Fred's team tonight.";

使用 /g 進(jìn)行全局替換

$_ = "home, sweet home!";
s/home/cave/g;
print "$_\n";              # "cave, sweet cave!"

全局替換的一個(gè)常用地方是將多個(gè)空格用單個(gè)空格替換掉:

$_ = "Input      data\t may have             extra whitespace.";
s/\s+/ /g;               # 現(xiàn)在是 "Input data may have extra whitespace."

現(xiàn)在已經(jīng)知道怎樣去掉多余的空格,那怎樣去掉開(kāi)頭和結(jié)尾的空白呢?這是非常容易的:

s/^\s+//;      #將開(kāi)頭的空白去掉
s/\s+$//;      #將結(jié)尾的空白去掉
s/^\s+|\s+$//g;   #將開(kāi)頭,結(jié)尾的空白去掉

不同的分隔符

如同 m//和 qw//一樣,我們也可以改變 s///的分隔符,。但這里使用了3個(gè)分隔符,因此有些不同。

s#^https://#http://#;

如果使用的是配對(duì)的字符,也就是說(shuō)其左字符和右字符不的,則必需使用兩對(duì):一對(duì)存放模式,一對(duì)存放替換的字符串,。此時(shí),分隔符甚至可以是不同的,。事實(shí)上,分隔符還可以使用普通的符號(hào)(非配對(duì)的)。下面三例是等價(jià)的:

s{fred}{barney};
s[fred](barney);
s<fred>#barney#;

可選的修飾符

除了/g 修飾符外,,替換操作中還可以使用 /i ,, /x , 和 /s, 這些在普通的模式匹配中已經(jīng)出現(xiàn)過(guò)的修飾符,。其順序是無(wú)關(guān)緊要的,。

s#wilma#Wilma#gi;              # 將所有的 WilmA,或者 WILMA 等等,由 Wilma 替換掉
s{_ _END_ _.*}{ }s;            # 將 END 標(biāo)記及其后面的行去掉

綁定操作

同 m// 一樣,我們也可以通過(guò)使用綁定操作符改變 s/// 的替換目標(biāo):

$file_name =~ s#^.*###s;                 # 將$file_name 中所有的 Unix 類(lèi)型的路徑去掉

大小寫(xiě)替換

有時(shí),希望確保被替換的字符串均是大寫(xiě)的(或者不是,視情況而定) 。這在 Perl 中只需使用某些修飾符就能辦到,。 \U 要求緊接著的均是大寫(xiě):

$_ = "I saw Barney with Fred.";
s/(fred|barney)/\U$1/gi;           # $_ 現(xiàn)在是 "I saw BARNEY with FRED."

同樣,也可以要求后面的均為小寫(xiě) \L :

s/(fred)|barney/\L$1/gi;         #$_現(xiàn)在是 "I saw barney with fred."

默認(rèn)時(shí),會(huì)影響到剩余的(替換的)字符串,。可以使用 \E 來(lái)改變這種影響:

s/(\w+) with (\w+)/\U$2\E with $1/I;       # $1 現(xiàn)在是 "I saw FRED with barney."

使用小寫(xiě)形式時(shí)( \l 和 \u ),只作用于下一個(gè)字符:

s/ (fred|barney)/\u$1/ig;     #$_現(xiàn)在是 "I saw FRED with Barney."

也可以同時(shí)使用它們,。如使用\u 和\L 表示 "第一個(gè)字母大寫(xiě),其它字母均小寫(xiě)",。 \L 和\u 可以按任意順序出現(xiàn)。Larry 意識(shí)到人們有時(shí)可能按相反順序使用它們,因此他將 Perl 設(shè)計(jì)成,在這兩種情況下都是將第一個(gè)字母大寫(xiě),其余的小寫(xiě),。 Larry 是個(gè)非常好的人,。

s/(fred|barney)/\u\L$1/ig; #$_現(xiàn)在為 "I saw Fred with Barney."

這些在替換中出現(xiàn)的大小寫(xiě)轉(zhuǎn)換的修飾符,也可在雙引號(hào)中使用:

print "Hello, \L\u$name\E, would you like to play a game?\n";

split 操作

另一個(gè)使用正則表達(dá)式的操作是 split , 它根據(jù)某個(gè)模式將字符串分割開(kāi)。這對(duì)于由制表符分割開(kāi),冒號(hào)分割開(kāi),空白分割開(kāi),或者任意字符分割開(kāi)的數(shù)據(jù)是非常有用的,。任何可在正則表達(dá)式之中 (通常,,是一個(gè)簡(jiǎn)單的正則表達(dá)式) 指定分離符 (separator) 的地方,均可用 split。其形式如下:

@fields = split /separtor/, $string;
@fields = split /:/, "abc:def:g:h";    # 返回 ("abc", "def", "g", "h")

/\s+/ 這個(gè)模式分隔符非常常見(jiàn):

my $some_input = "This    is a \t             test.\n";
my @args = split /\s+/, $some_input;           # ("This", "is", "a", "test." )

默認(rèn)時(shí),split 對(duì)$_操作,模式為空白:

my @fields = split;      # 同 split /\s+/, $_;

join 函數(shù)

join 函數(shù)不使用模式,但它完成同 split 相反的操作:split 將一個(gè)字符串分割開(kāi),而 join 函數(shù)將這些分割的部分組合成一個(gè)整體,。join 函數(shù)類(lèi)似于 :

my $result = join $glue, @pieces;

join 函數(shù)的第一個(gè)參數(shù)是粘合元素(glue),它可以是任意字符串,。剩下的參數(shù)是要被粘合的部分。join 將粘合元素添加在這些部分之間,并返回其結(jié)果:

my $x = join ":", 4, 6, 8, 10, 12; #$x 為 "4:6:8:10:12"

列表上下文中的 m//

在列表 context 中使用模式匹配(m//)時(shí),如果匹配成功返回值為內(nèi)存變量值的列表;如果匹配失敗則為空列表:

$_ = "Hello there, neighbor!";
my($first, $second, $third) =/(\S+) (\S+), (\S+)/;
print “$second is my $third\n”  ;

在 s/// 中介紹的 /g 修飾符也可在 m// 中使用,它允許你在字符串中的多處進(jìn)行匹配,。在這里,由括號(hào)括起來(lái)的模式將在每一次匹配成功時(shí)返回其內(nèi)存中所存放的值:

my $text = "Fred dropped a 5 ton granite block on Mr. Slate";
my @words = ($text =~ /([a-z]+)/ig);
print "Result: @words\n";
#Result: Fred dropped a ton granite block on Mr slate

如果有不止一對(duì)括號(hào),每一次返回不止一個(gè)字符串,。例如將字符串放入 hash 中,如下:

my $data = "Barney Rubble Fred Flintstone Wilma Flintstone";
my %last_name = ($data =~ / (\w+)\S+(\w+)/g);

每當(dāng)模式匹配成功時(shí),將返回一對(duì)值。這些一對(duì)一對(duì)的值就成了 hash 中的 key/value 對(duì),。

更強(qiáng)大的正則表達(dá)式

非貪婪的數(shù)量詞

各符號(hào)對(duì)應(yīng)的非貪婪匹配:

+  -->  /fred.+?barney/
*  -->  s#<BOLD>(.*?)</BOLD>#$1#g;
{5,10}?
{8,}?
?  -->  ??

在命令行進(jìn)行修改

$ perl –p –i.bak –w –e 's/Randall/Randal/g' fred*.dat

-p 要求 Perl 為你寫(xiě)一個(gè)程序,。它算不上是一個(gè)完整的程序;看起來(lái)有些像下面的:

while(<>) {
print;
}

更多控制結(jié)構(gòu)

unless 控制結(jié)構(gòu)

在 if 控制結(jié)構(gòu)中,只有條件為真時(shí),才執(zhí)行塊中的代碼。如果你想在條件為假時(shí)執(zhí)行,可以使用 unless:

unless ($fred =~ /^[A-Z_]\w*$/i) {
print "The value of \$fred doesn't look like a Perl identifier name.\n";
}

unless 的含義是:除非條件為真,否則執(zhí)行塊中的代碼,。這和在 if 語(yǔ)句的條件表達(dá)式前面加上!(取反)所得結(jié)果是一樣的,。

另一種觀(guān)點(diǎn)是,可以認(rèn)為它自身含有 else 語(yǔ)句。如果不太明白 unless 語(yǔ)句,你可以把它用 if 語(yǔ)句來(lái)重寫(xiě)(頭腦中,或者實(shí)際的重寫(xiě)) :

if ($fred =~ /^[A-Z_]\w*$/i) {
#什么也不做
} else {
print "The value of \$fred doesn't look like a Perl identifier name.\n";
}

unless 和 else 一起

unless ($mon =~ /^Feb/) {
print "This month has at least thirty days.\n";
} else {
print "Do you see what's going on here?\n";
}
也可以同時(shí)使用它們

until 控制結(jié)構(gòu)

有時(shí),希望將 while 循環(huán)的條件部分取反,。此時(shí),可以使用 until:

until ($j > $i) {
$j *= 2;
}

表達(dá)式修飾符

為了得到更緊湊的形式,表達(dá)式后可以緊接控制修飾語(yǔ),。如,if 修飾語(yǔ)可以像 if 塊那樣使用:

print "$n is a negative number.\n" if $n<0;

等同下面代碼:

if ($n < 0) {
print "$n is a negative number.\n";
}

雖然被放在后面,條件表達(dá)式也是先被求值的,。這和通常的的從左到右的順序相反,。要理解 Perl 代碼,應(yīng)當(dāng)像 Perl 內(nèi)部的編譯器那樣,將整個(gè)語(yǔ)句讀完,來(lái)其具體的含義。

還有一些其它的修飾語(yǔ):

&error ("Invalid input") unless &valid($input);
$i *= 2 unitl $i > $j;
print "", ($n += 2) while $n <10;
&greet($_) foreach @person;

The Naked Block 控制結(jié)構(gòu)

被稱(chēng)為“裸的”塊是指沒(méi)有關(guān)鍵字或條件的塊,。假如有一個(gè) while 循環(huán),大致如下:

while(condition) {
body;
body;
body;
}

將關(guān)鍵字 while 和條件表達(dá)式去掉,則有了一個(gè)“裸的”塊:

{
body;
body;
body;
}

“裸的”塊看起來(lái)像 while 或 foreach 循環(huán),除了它不循環(huán)外;它執(zhí)行“循環(huán)體”一次,然后結(jié)束,。它根本就沒(méi)循環(huán)!

你也可能在其它地方使用過(guò)“裸的”塊,這通常是為臨時(shí)變量提供作用域:

{
print "Please enter a number:";
chomp(my $n = <STDIN>);
my $root = sqrt $n;            #計(jì)算平方根
print "The square root of $n is $root.\n";
}

elsif 語(yǔ)句

自增和自減 (同C)

my @people = qw{ fred barney fred Wilma dino barney fred pebbles};
my %count;                              #新的空的 hash
$count{$_}++ foreach @people;       #根據(jù)情況創(chuàng)建新的 keys 和 values

第一次執(zhí)行 foreach 循環(huán)時(shí),$count{$_}自增1。此時(shí),$count{"fred"} 從 undef (由于之前 hash 中不存在)變成1,。第二次執(zhí)行 foreach 循環(huán)時(shí),$count{"barney"} 變成1; 接著,$count{"fred"} 變成2,。每執(zhí)行一次循環(huán),%count 中的某個(gè)元素增1,或者新元素被創(chuàng)建,。循環(huán)結(jié)束時(shí),$count{"fred"} 值為3。這提供了一種查看某個(gè)元素是否存在于列表之中,以及其出現(xiàn)次數(shù)的方法,。

for 控制結(jié)構(gòu) (同C)

for (initialization; test; increment) {
body;
body;
}

foreach 和 for 的關(guān)系

對(duì)于 Perl 解析器(parser)而言, 關(guān)鍵字 foreach 和 for 是等價(jià)的,。也就是說(shuō), Perl 遇見(jiàn)其中之一時(shí), 和遇見(jiàn)另一個(gè)是一樣的。Perl 通過(guò)括號(hào)能理解你的目的,。如果其中有兩個(gè)分號(hào),則是 for 循環(huán)(和我們剛講的類(lèi)似); 如果沒(méi)有,則為 foreach 循環(huán):

for (1..10) {                                #實(shí)際上是 foreach 循環(huán),從1到10
print "I can count to $_!\n";
}

這實(shí)際是一個(gè) foreach 循環(huán),但寫(xiě)作 for,。除了本例外,本書(shū)后面均寫(xiě)作 foreach。在實(shí)際代碼中,你覺(jué)得 Perler 會(huì)輸入這四個(gè)多余的字符嗎?除了新手外,一般均寫(xiě)作 for,你也應(yīng)當(dāng)像 Perl 那樣,通過(guò)查看括號(hào)內(nèi)分號(hào)個(gè)數(shù)來(lái)判斷,。

循環(huán)控制

last 操作

last 會(huì)立刻結(jié)束循環(huán),。(這同 C 語(yǔ)言或其它語(yǔ)言中的 "break" 語(yǔ)句類(lèi)似)。它從循環(huán)塊中“緊急退出” ,。當(dāng)執(zhí)行到 last,循環(huán)即結(jié)束,如下例 :

#輸出所有出現(xiàn) fred 的行,直到遇見(jiàn) _ _END_ _標(biāo)記
while(<STDIN>){
if(/_ _ END_ _/){
#這個(gè)標(biāo)記之后不會(huì)有其它輸入了
last;
}elsif(/fred/){
print;
}
}
##last 跳轉(zhuǎn)到這里##

next 操作 (同C的中 continue)

redo 操作

循環(huán)控制的第三個(gè)操作是 redo,。它會(huì)調(diào)到當(dāng)前循環(huán)塊的頂端,不進(jìn)行條件表達(dá)式判斷以及接著本次循環(huán)。(在 C 或類(lèi)似語(yǔ)言中沒(méi)有這種操作)下面是一個(gè)例子:

# 輸入測(cè)試
my @words = qw{ fred barney pebbles dino Wilma betty };
my $errors = 0;
foreach(@words){
##redo 跳到這里##
print "Type the word '$_' : ";
chomp(my $try = <STDIN>);
if($try ne $_){
print "sorry -- That's not right.\n\n";
$errors++;
redo;                          #跳轉(zhuǎn)到循環(huán)頂端
}
}
print "You've completed the test, with $errors errors.\n";

標(biāo)簽塊

要給循環(huán)體加上標(biāo)簽,可在循環(huán)前面加上標(biāo)簽和冒號(hào),。在循環(huán)體內(nèi),可以根據(jù)需要在 last, next,或n者 redo 后加上標(biāo)簽名,如:

LINE: while(<>){
foreach (split){
last LINE if /_ _END_ _/; # 退出 LINE 循環(huán)
...
}
}

邏輯操作符 && 和 ||

短路操作符

和 C(以及類(lèi)似的語(yǔ)言)不同的地方是,短路操作的結(jié)果是最后被執(zhí)行語(yǔ)句的返回值,而非僅僅是一個(gè) Boolean 值,。

my $last_name = $last_name{$someone} || '(No last name)';

三元操作符 ?:

當(dāng) Larry 決定 Perl 應(yīng)當(dāng)具有哪些操作符時(shí),他不希望以前的 C 程序員在 Perl 中找不到 C 中出現(xiàn)過(guò)的操作符,因此他在 Perl 中實(shí)現(xiàn)了所有 C 的操作符。這意味著 C 中最容易混淆的操作符:三元操作符(?:)也被移植過(guò)來(lái)了,。雖然它帶來(lái)了麻煩,但有時(shí)也是非常有用的,。

Express ? if_true_expr : if_false_expr
my $size =
($width < 10 ) ? "small":
($width < 20) ? "medium":
($width < 50) ? "large":
"extra_large"; #default

控制結(jié)構(gòu): 使用部分求值的操作符

前面三個(gè)操作符,均有一個(gè)共同的特殊性質(zhì):根據(jù)左側(cè)的值(true 或 false),來(lái)判斷是否執(zhí)行右側(cè)代碼。有時(shí)會(huì)被執(zhí)行,有時(shí)不會(huì),。由于這個(gè)理由,這些操作符有時(shí)叫做部分求值(partial-evaluation)操作符,因?yàn)橛袝r(shí)并非所有的表達(dá)式均被執(zhí)行,。部分求值操作符是自動(dòng)的控制結(jié)構(gòu)。并非 Larry 想引入更多的控制結(jié)構(gòu)到 Perl 中來(lái),。而是當(dāng)他決定將這些部分求值操作符引進(jìn) Perl 后,它們自動(dòng)成了控制結(jié)構(gòu),。畢竟,任何可以激活或解除某塊代碼的執(zhí)行即被稱(chēng)作控制結(jié)構(gòu)。

文件校驗(yàn)

文件檢測(cè)操作

如果程序會(huì)建立新的文件,在程序創(chuàng)建新文件之前,我們應(yīng)先確定是否存在同名的文件,以免重要數(shù)據(jù)被覆蓋掉,。對(duì)于這種問(wèn)題,我們可以使用– 選項(xiàng),檢測(cè)是否存在相同名字的文件:

die "Oops! A file called '$filename' already exists.\n"
if -e $filename;

如果文件在過(guò)去28 天內(nèi)都未被修改,輸出警告:

warn "Config file is looking pretty old!\n"
if -M CONFIG > 28;

下例首先檢查文件列表,,找到那些大于 100KB 的文件。如果一個(gè)文件僅是很大, 我們不一定會(huì)將其移到備份磁帶上去,,除非同時(shí)其在最近 90 天內(nèi)都未被訪(fǎng)問(wèn),。

my @ariginal_files = qw/ fred barney betty Wilma pebbles dino bam-bamm /;
my @big_old_files; #要移到備份磁帶上的文件
foreach my $filename (@original_files){
push @big_old_files, $filename
if -s $filename > 100_100 and -A $filename > 90;
}
-r 文件或目錄對(duì)此(有效的)用戶(hù)(effective user)或組是可讀的
-w 文件或目錄對(duì)此(有效的)用戶(hù)或組是可寫(xiě)的
-x 文件或目錄對(duì)此(有效的)用戶(hù)或組是可執(zhí)行的
-o 文件或目錄由本(有效的)用戶(hù)所有
-R 文件或目錄對(duì)此用戶(hù)(real user)或組是可讀的
-W 文件或目錄對(duì)此用戶(hù)或組是可寫(xiě)的
-X 文件或目錄對(duì)此用戶(hù)或組是可執(zhí)行的
-O 文件或目錄由本用戶(hù)所有
-e 文件或目錄名存在
-z 文件存在,大小為 0(目錄恒為 false)
-s 文件或目錄存在,大小大于 0(值為文件的大小,單位:字節(jié))
-f 為普通文本
-d 為目錄
-l 為符號(hào)鏈接
-S 為 socket
-p 為管道(Entry is a named pipe(a "fifo"))
-b 為 block-special 文件(如掛載磁盤(pán))
-c 為 character-special 文件(如 I/O 設(shè)備)
-u setuid 的文件或目錄
-g setgid 的文件或目錄
-k File or directory has the sticky bit set
-t 文件句柄為 TTY(系統(tǒng)函數(shù) isatty()的返回結(jié)果;不能對(duì)文件名使用這個(gè)測(cè)試)
-T 文件有些像“文本”文件
-B 文件有些像“二進(jìn)制”文件
-M 修改的時(shí)間(單位:天)
-A 訪(fǎng)問(wèn)的時(shí)間(單位:天)
-C 索引節(jié)點(diǎn)修改時(shí)間(單位:天)

stat 和 lstat 函數(shù)

my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blockes)
= stat($filename);

localtime 函數(shù)

my($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst)
= localtime $timestamp;
my $timestamp = 1180630098;
my $date = localtime $timestamp;

gmtime

my $now = gmtime; #得到當(dāng)前的時(shí)間

位操作

10 & 12 按位與;當(dāng)操作數(shù)相應(yīng)位均為 1 時(shí)結(jié)果為 1 (本例結(jié)果為 8)
10 豎線(xiàn) 12 按位或;當(dāng)操作數(shù)中相應(yīng)位有一個(gè)為 1 則結(jié)果為 1(本例結(jié)果為 14)
10 ^ 12 按位異或;當(dāng)操作數(shù)中相應(yīng)位有且僅有一個(gè)為 1,結(jié)果才為 1(本例結(jié)果 6)
6 << 2 位左移,將左邊操作數(shù)左移右邊操作數(shù)所指定的位數(shù),被移出的位置(右邊)補(bǔ) 0(結(jié)果為 24)
25 >> 2 位右移,將左邊操作數(shù)右移動(dòng)右邊操作數(shù)所指定的位數(shù),丟棄多余的位數(shù)(左邊) (本例結(jié)果位 6)
~10 位取反,也叫做一元位補(bǔ)運(yùn)算;其返回值為操作數(shù)中相應(yīng)位取反的值(本例為 0Xfffffff5,這和具體情況有關(guān))

目錄操作

在目錄樹(shù)上移動(dòng)

chdir "/etc" or die "cannot chdir to /etc: $!";

由于這是系統(tǒng)請(qǐng)求,錯(cuò)誤發(fā)生時(shí)將給變量$!賦值。通常應(yīng)當(dāng)檢查$!的值,因?yàn)樗鼘⒏嬖V你 chdir 失敗的原因。

Globbing

通常,shell 將每個(gè)命令行中的任何的文件名模式轉(zhuǎn)換成它所匹配的文件名。這被稱(chēng)作 globbing,。例如,在 echo 命令后使用了文件名模式*.pm,shell 會(huì)將它轉(zhuǎn)換成它所匹配的文件名:

$ echo *.pm
barney.pm dino.pm fred.pm wilma.pm
$
$ cat > show_args
foreach $arg (@ARGV) {
print "one arg is $arg\n";
}
^D
$ perl show_args *
...

show-args 不需要知道如何進(jìn)行 globbing,這些名字已經(jīng)被處理后存在@ARGV 中了,。

在 Perl 程序中也可以使用 Glob 匹配,。

my @all_files = glob "*" ;
my @pm_files = glob "*.pm";

@all_files 得到了當(dāng)前目錄下的所有文件,這些文件按照字母排序的,不包括由點(diǎn) (.)開(kāi)頭的文件。

Globbing 的替換語(yǔ)法

雖然我們?nèi)我獾氖褂?globbing 這個(gè)術(shù)語(yǔ),我們也談?wù)?glob 操作,但在許多使用 globbing 的程序中并沒(méi)有出現(xiàn) glob 這個(gè)字眼。為什么呢?原因是,許多這類(lèi)代碼在 glob 操作被命名前就寫(xiě)好了,。它使用一對(duì)尖括號(hào)(<>), 和從文件句柄讀入操作類(lèi)似:

my @all_files = <*>;     # 基本上同 @all_files = glob "*" 一樣
my $dir = "/etc";
my @dir_files = <$dir/* $dir/.*>;

目錄句柄

從給定目錄得到其文件名列表的方法還可以使用目錄句柄(directory handle),。目錄句柄外形及其行為都很像文件句柄。打開(kāi)(使用 opendir 而非 open),從中讀入(使用 readdir 而非 readline),關(guān)閉(使用 closedir 而非 close),。不是讀入文件的內(nèi)容,而是將一個(gè)目錄中的文件名(以及一些其它東西)讀入,如下例:

my $dir_to_process = "/etc";
opendir DH, $dir_to_process or die "Cannot open $dir_to_process: $!";
foreach $file(readdir DH) {
print "One file in $dir_to_process is $file\n";
}
closedir DH;

刪除文件 unlink

unlink "slate", "bedrock", "lava";

這里有一個(gè)鮮為人知的 Unix 事實(shí),。你可以有一個(gè)文件不可讀,不可寫(xiě),不可執(zhí)行,甚至你并不擁有它,例如屬于別人的,但你仍然可以刪除它。這時(shí)因?yàn)?unlink 一個(gè)文件的權(quán)限同文件本身的權(quán)限是沒(méi)有關(guān)系的;它和目錄所包含的文件權(quán)限有關(guān)。

重命名文件

rename "over_there/some/place/some_file", "some_file";

鏈接文件

要找出符號(hào)連接指向的地方,使用 readlink 函數(shù),。它會(huì)告訴你符號(hào)連接指向的地方,如果參數(shù)不是符號(hào)連接其返回 undef:

my $where = readlink "carroll";        # 得到 "dodgson"
my $perl = readlink "/usr/local/bin/perl"  # 可能得到 Perl 放置的地方

創(chuàng)建和刪除目錄

mkdir "fred", 0755 or warn "Cannot make fred directory: $!";
rmdir glob "fred/*";          # 刪除 fred/下面所有的空目錄

修改權(quán)限

chmod 0755, "fred", "barney";

改變所有者

my $user = 1004;
my $group = 100;
chown $user, $group, glob "*.o";

如果要使用用戶(hù)名:

defined(my $user = getpwnam "merlyn") or die "user bad";
defined(my $group = getprnam "users") or die "group bad";
chown $user, $group, glob "/home/Merlyn/*";

defined 函數(shù)驗(yàn)證返回值是否為 undef, 如果請(qǐng)求的 user 或 group 不存在,則返回 undef。chown 函數(shù)返回其改變的文件的個(gè)數(shù),而錯(cuò)誤值被設(shè)置在$!之中。

改變時(shí)間戳

my $now = time;
my $ago = $now -24*60*60;  # 一天的秒數(shù)
utime $now,$ago,glob "*"   # 設(shè)成當(dāng)前訪(fǎng)問(wèn)的,一天之前修改的

字符串和排序

使用索引尋找子串

$where = index($big, $small);

Perl 查找子串第一次在大字符串中出現(xiàn)的地方,返回第一個(gè)字符的位置,。字符位置是從 0 開(kāi)始編號(hào)的,。如果子串在字符串的開(kāi)頭處找到,則 index 返回 0,。如果一個(gè)字符后,則返回1,依次類(lèi)推,。如果子串不存在,則返回-1,。

使用 substr 操作子串

$part = substr($string, $initial_position, $length);

它有三個(gè)參數(shù):一個(gè)字符串,一個(gè)從 0 開(kāi)始編號(hào)的初始位置(類(lèi)似于 index 的返回值) ,以及子串的長(zhǎng)度。返回值是一個(gè)子串:

my $mineral = substr("Fred J. Flintstone", 8, 5);   # 得到 "Flint"
my $rock = substr "Fred J. Flintstone", 13, 1000;  # 得到 "stone"
my $pebble = substr "Fred J. Flintsone", 13;     #  同上,,得到 "stone"
my $out = substr ("some very long string", -3, 2);       # $out 得到 "in"

substr 選則的子串可以就地修改,!

#!/usr/bin/perl -w
use strict;
my $string = "Hello, world!";
substr($string,6) = "Jian Lee!";
print $string . "\n";

最后輸出為: “Hello,Jian Lee!”

使用 sprintf 格式化數(shù)據(jù)

sprintf 函數(shù)的參數(shù)和 printf 的參數(shù)完全相同(除了可選的文件句柄外), 但它返回的是被請(qǐng)求的字符串,而非打印出來(lái),。這對(duì)于希望將某個(gè)格式的字符串存入變量以供將來(lái)使用的情況非常方便,或者你想比 printf 提供的方法,更能控制結(jié)果:

my $data_tag = sprintf   "%4d/%02d/%02d %02d:%02d:%02d", $yr, $mo, $da, $h, $m, $s;

進(jìn)程管理

system 函數(shù)

在 Perl 中調(diào)用子進(jìn)程來(lái)運(yùn)行程序的最簡(jiǎn)單方法是使用 system 函數(shù),。例如,要調(diào)用 Unix 的 date 命令,看起來(lái)如下:

system "date";

系統(tǒng)函數(shù)的參數(shù)和通常在 shell 中輸入的是一樣的。如果是復(fù)雜一些的命令,如 “ – $HOME” ,我們也只需將它們放入?yún)?shù)中:

system 'ls -l $HOME';

我們這里將雙引號(hào)變成了單引號(hào),因?yàn)?HOME 是一個(gè) shell 變量,。否則,shell 看不到美元符號(hào),因?yàn)?Perl 會(huì)將它用值進(jìn)行替換,。當(dāng)然,我們也可以這樣寫(xiě):

system "ls -l \$HOME";

exec 函數(shù)

exec 和 system 完全一樣,,除了一點(diǎn)!exec 打開(kāi)一個(gè)進(jìn)程代替當(dāng)前的 Perl 程序教程,,exec 執(zhí)行的進(jìn)程結(jié)束不再返回到perl教程。

環(huán)境變量

Perl , 環(huán)境變量可以由 %ENV 得到,。

$ENV{'PATH'} =  "/home/rootbeer/bin:$ENV('PATH')";
delete $ENV{'IFS'};
my $make_result = system "make";

使用反引號(hào)得到輸出

my $now = `date`;                # 捕獲 date 的輸出
print "The time is now $now";    # 已經(jīng)有換行符

像文件句柄一樣處理進(jìn)程

開(kāi)始一個(gè)并發(fā)(并行)子進(jìn)程的語(yǔ)法是將命令作為“文件名”傳給 open,并在其前面或后面加上豎線(xiàn)(|),豎線(xiàn)是“管道(pipe)”符,。基于這些原因,這通常叫做管道打開(kāi) (piped open) :

open DATE, "date|" or die "Cannot pipe from date: $!";
open MAIL, "|mail merlyn" or die "Cannot pipe to mail: $!";

fork 函數(shù)

defined (my $pid= fork) or die "Cannot fork: $!";
unless ($pid){
#子進(jìn)程在這里
exec "date";
die "cannot exec date: $!";
}
#父進(jìn)程在這里
waitpid($pid, 0);

發(fā)送和接受信號(hào)

kill 2, 4201 or die "Cannot signal 4201 with SIGINT: $!";

Perl 模塊

查找

http://search./

$ perldoc CGI

安裝模塊

通常模塊使用 MakeMaker ,,可以這樣安裝:

$ perl Makerfile.PL
# $ perl Makerfile.PL PREFIX=/Users/fred/lib
$ make install

一些模塊的創(chuàng)建者使用另一個(gè)模塊:Module::Build,來(lái)構(gòu)造及安裝他們的模塊,。此時(shí)的命令如下:

$ perl Build.PL
$./Build install

使用 CPAN.pm

$ perl -MCPAN -e shell
$ cpan Module::CoreList LWP CGI::Prototype

使用簡(jiǎn)單的模塊

File::Basename

use File::Basename;
my $name = "/usr/local/bin/perl";
my $basename = basename $name; #得到 "perl"

僅使用模塊中的一些函數(shù)

use File::Basename qw/ basename /;

下面做法不引入任何函數(shù):

use File::Baename qw/ /;
use File::Basename ( );

沒(méi)有引入任何函數(shù)時(shí),,如果要使用函數(shù),就必須用全名:

use File:Basename qw/ /;            # 沒(méi)有引入函數(shù)
my $betty = &dirname($wilma);       # 使用我們自己的子程序 &dirname(這里沒(méi)有顯示)
my $name = "/usr/local/bin/perl";
my $dirname = File::Basename::dirname $name; # 使用模塊中的 dirname

File:Spec 模塊

use File::Spec;
#得到上面的$dirname, $basename 的值
my $new_name = File::Spec->catfile($dirname, $basename);
rename($old_name, $new_name)
or warn "Can't rename '$old_name' to '$new_name': $!";

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶(hù)發(fā)布,,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多