Perl 入門

1. Perl 也允許使用非10 爲底的數字。八進制以0 開頭,十六進制以0x 開頭,二進制0b 開頭.在十
六進制中A 到F(或者a 到f)分別表示10 到15:
0377 #八進制數字377,等同於十進制數字255
0xff #十六進制數字FF,等同於十進制數字255
0b11111111 #等同於十進制數字255

2. Perl 除了提供通常的操作符加(+),減(-),乘(*),除(/)等等之外:
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 #通常是浮點除,3.33333… …
還提供了模數運算符(%)。10%3 的值是10 除以3 的餘數
如2**3,表示2 的3 次方,等於

3. 字符串是一串字符(如hello)。字符串可能是字符的任意組合◆。最短的字符串不含任何字符。最長的字符串,可以填滿整個內存.
◆和C,C++不同,Perl 中NUL 字符沒有特殊的含義。Perl 能計算長度,不用靠null 來判斷字符串是否結束。
和數字一樣,字符串也可由文字符號(literal)來表示,它用來在Perl 程序中代表某個字符串。有兩種類型的字符串:單引號字符串和雙引號字符串。

除了單引號,或者反斜線(包括換行字符,如果字符串在下一行繼續)之外的任何字符都表示它自身
‘fred’ #四個字符:f,r,e,d
‘barney’#六個字符
‘’ #空字符(沒有字符)
‘Don’t let an apostrophe end this string prematruely!’
‘the last character of this string is a backslash: \\’
‘hello\n’#hello 緊跟着反斜線和n
‘hello
there’ #hello,換行,there (共11 個字符)
‘\’\\’ #單引號(’)跟着反斜線(\)

雙引號字符串和在其它語言類似。它也是字符的序列,不同點在於,其由雙引號括起來的。現在,反斜線可以用來表示控制字符,或者八進制,十六進制數的表示。下面是一些雙引號字符串的例子:
“barney”#等同於‘barney’
“hello world\n”#hello world,換行
“the last character of this string is a quote mark:\””
“coke\tsprite”# coke, a tab(一個製表符), sprite

“hello”. “world” # 同於“helloworld”
“hello”. ‘’. “world”#同於“hello world”
‘hello world’. “\n” #同於“hello world\n”

“fred”x 3 # “fredfredfred”
“barney”x (4+1) # “barney”x 5, “barneybarneybarneybarneybarney”
5 x 4 #實際上是“5”x 4, “5555”

4. 數字和字符串之間的自動轉換
當在需要數字的地方使用了字符串(如,乘法),Perl 將自動把字符串轉換爲其等價的數字,就像輸入的是十進制浮點數一
樣◆。因此“12”* “3”將給出36。後面的非數字部分和前面的空格將被去掉,如“12fred34”* “3”將給出36 而不會用任何
提示◆。在極端情形,當一個不含任何數字的字符串將別轉換爲0。如,將“fred”當作數字來使用時。


5. 標量變量可以存放一個標量值。
標量變量的名字由一個美圓符號($)後接Perl 標識符:由字母或下劃線開頭,後接字母,數字,或者下劃線。或者說由字母,數字和下劃線組成,但不能由數字開頭。大小寫是嚴格區分的:變量$Fred 和變量$fred
是不同的。任意字母,數字,下劃線都有意義,如:
$a_very_long_variable_that_ends_in_1

標量賦值
$fred = 17; #將17 賦給變量$fred
$barney =‘hello’; #將五個字母的字符串‘hello’賦給$barney
$barney = $fred + 3;# 將$fred 的值加上三賦給$barney (20)
$barney= $barney*2;#將變量$barney 乘2 再賦給$barney (40)

$barney = $barney*3;    $barney*=3;
$str = str . “”; #$str 後接空格
$str .= “”’; #同上


6. 字符串中標量變量的內插
$mean = “brontosaurus steak”;
$barney = “fred ate a $meal”; #$barney 現在是“fred ate a brontosaurus steak”
$barney = ‘fred ate a’. $meal; #同上

如果一個變量未被賦值,則將使用空值替換
print “$fred”; #引號是沒有必要的
print $fred; #更好的寫法

在字符串中變量前($符號前)加上反斜線(\),變量將不會被內插(替換):
$fred = ‘hello’;
print “The name is \$fred .\n”; #打印出美圓符號,變量不會被其值替換
print ‘The name is $fred’. “\n”; #同上
print "Try to get value of \$fred: $fred\n";

變量名將是字符串中有意義的最長的那一個。這可能在當你需要在某次匹配就替換的情況下出問題。Perl 提供了一種類似於shell 的分隔符:花括號({})。用花括號將變量名括起來。或者將字符串分隔成幾個部分,再用連接符( . )串起來:
$fred = "Kelvin";
$freds = "Damon";
print "Try to get value of \n\$fred: ${fred}s\n\$freds: $freds\n${freds}\n";

7. 比較運算符
35 != 30+5 #false
35 == 35.0 #true
‘35’eq‘35.0’ #false (按照字符串比較)
‘fred’lt ‘barney’ #false
‘fred’lt ‘free’ #true
‘fred’eq ‘fred’ #true
‘fred’eq ‘Fred’ #false
‘’gt ‘’ #true

8. 控制結構
if
if($name gt ‘fred’){
print “‘$name’comes after ‘fred’in sorted order.\n”;
}else{
print “‘$name’does not come after ‘fred’.\n”;
print “Maybe it’s the same string, in fact.\n”;
}

while
$count = 0;
while ($count < 10) {
$count + = 2;
print “count is now $count\n”; #打印出2 4 6 8 10
}

foreach
@rocks = qw/ bedrock slate lava /;
foreach $rocks(@rocks){
$rock = “\t$rock”; #@rocks 的每一個元素前加入一個tab
$rock . = “\n”; #每一個元素後加一個換行符
}
print “The rocks are:\n”,@rocks; #每一個元素都被縮進了,並且一個元素佔一行

類似Boolean類型
$is_bigger = $name gt‘fred’;
if($is_bigger){… }
判斷依據
● 如果值爲數字,0 是false;其餘爲真
● 如果值爲字符串,則空串(‘’)爲false;其餘爲真
● 如果值的類型既不是數字又不是字符串,則將其轉換爲數字或字符串後再利用上述規則◆。
這意味着undef(很快會看到)爲false。所有的引用(在Alpaca 書中有詳細討論)都是true。
字符串‘0’是唯一一個非空但值爲0 的串。

9. 用戶輸入
$line = <STDIN>;
if($line eq “\n”){
print “That was just a blank line!\n”;
}else{
print “That line of input was: $line”;
}



完全正確,只是有未初始化的警告:
#n = 1;
while($n < 3){
$sum += $n;
$n +=1;
}
print "The total was $sum.\n";

10. 常用函數
define:檢查是否初始化
$madonna = <STDIN>;
If ($defined ($madonna)){
print “The input was $madonna”;
}else{
print “No input available!\n”;
}

qw:
實踐表明,字符串的列表(如上例)在Perl 中經常使用。有一種簡便的方法可以不用輸入大量的引號而達到類似的功能,那就是使用qw。qw 表示“quoted words”或者“quoted by whitespace”
(“fred”, “barney”, “betty”, “wilma”, “dino”)
qw(fred barney betty wilma dino ) #同上,但輸入更少

chomp:去掉最後的\n
$line = "ab\\nc\n";
print $line;
chomp($line);
print $line;
chomp (@lines = <STDIN>); #讀入所有的行,不包括換行符

reverse
reverse(逆轉)操作將輸入的一串列表(可能是數組)按相反的順序返回。如果不喜歡範圍操作符: .,只能從小到大, 那可以使用 reverse 來解決這個問題:
@fred = 6 .
.10;
@barney = reverse (@fred);
@wilma = reverse 6 .
.10;
@fred = reverse @fred;
#得到 10,9,8,7,6
#同上,沒有使用額外的數組

sort:需要將結果存回原數據結構
sort 操作將輸入的一串列表(可能是數組)根據內部的字符順序進行排序。如對於 ASCII 字符串,將根據 ASCII 序進行排 序。當然,ASCII 中有一些奇怪的地方,如大寫字母在小寫字符的前面,數字在字符的前面,而標點符號散佈在各處。但按 ASCII 排序只是其默認的行爲,在第十三章中,可以看到如何按你想要的順序進行排序的方法:
@rocks = qw/ bedrock slate rubble granite /; #得到 bedrock, granite, rubble, slate
@sorted = sort(@rocks);
@back = reverse sort @rocks; #爲 slate 到 bedrock
@rocks = sort @rocks;
@numbers = sort 97 .
.102;
#將排序的值寫回@rocks
#得到 100,101,102,97,98,99

scalar:告訴 Perl 提供一個標量 context
偶爾,你可能需要標量 context 而 Perl 期望的是列表。這種情況下,可以使用函數 scalar。它不是一個真實的函數因爲其僅 是告訴 Perl 提供一個標量 context:
@rocks = qw(talc quartz jade obsidian);
print “
How many rocks do you have?\n”
;
print “ have ” @rocks, “
I
,
rocks!\n”
;
print “ have ” scalar @rocks, “
I
,
rocks!\n”
;
#錯誤,輸出 rocks 的名字
#正確,輸出其數字

reverse: hash 的反轉,鍵值調換,如有重複鍵,最後一次的值保留:
%inverse_hash = reverse %any_hash;


keys 函數會返回此 hash 的所有 keys,values 函數將返回所有的 values。如果 hash 中沒有元素,則此函數將返回空列表:
my %hash = (“
a”=>1, “
b”=>2, “
c”=>3);
my @k = keys %hash;
my @v = values %hash;


11. 數組和列表
$arr[0] = "2";
$arr[5] = "4";
print $arr[0]*$arr[$#arr]."\n";  #8
print $arr[0]*$arr[$#arr+1]."\n"; #0
print $arr[0]*$arr[-1]."\n";  #8. if use -2, it represents nodes before the last one

@rocks = qw(aa bb cc dd);
$num = $#rocks;
print "$rocks[$num]\n";

數組是由括號括起來並且其元素由逗號分隔開的列表。這些值組成了數組的元素:
(1 ..5) #同(1,2,3,4,5)
(1.7..5.7) #同上— 最小值和最大值被轉換成整數
(5 ..1) #空列表— ..中的左值應小於右值,否則爲空
(0,2 .. 6,10,12)#同(0,2,3,4,5,6,10,12)
($m ..$n) #由$m 和$n 的值決定
(0 .. $#rocks) #上節中有$#rocks 的介紹

列表賦值
($fred, $barney, $dino) = (“flintstone”, “rubble”, undef);
($fred, $barney) = ($barney, $fred) #交換兩個變量
($betty[0],$betty[1]) = ($betty[1],$betty[0]);

($fred, $barney) = qw <flintstone rubble slate granite>; #兩個值被忽略了
($wilma,$dino) = qw[flintstone]; #$dino 爲undef

@rocks = qw / bedrock slate lava /;
@tiny = (); #空表
@giant = 1..1e5; #包含100,000 個元素的表
@stuff = (@giant, undef, @giant); #包含200,001 個元素的表
@dino = “granite”;
@quarry = (@rocks, “crushed rock”, @tiny, $dino);
@copy = @quarry; #將一個數組中的值拷貝的另一個數組中

pop
@array = 5..9;
$fred = pop(@array); #$fred 得到9,@array 現在爲(5,6,7,8)
$barney = pop @array; #$barney gets 8, @array 現在爲(5,6,7)
pop @array; #@array 現在爲(5,6)(7 被丟棄了)
如果數組爲空,那pop 什麼也不做(因爲沒有元素可以移出),並返回undef。

push
push(@array,0); #@array 現在爲(5,6,0)
push @array,8; #@array 現在爲(5,6,0,8)
push @array,1..10; #@array 現在多了10 個元素
@others =qw/9 0 2 1 0 /;
push @array,@others; #@array 現在又多了5 個元素(共有19 個)

shift && unshift
push 和pop 對數組的末尾進行操作(或者說數組右邊有最大下標的元素,這依賴於你是怎樣思考的)。相應的,unshift 和shift 對一個數組的開頭進行操作(數組的左端有最小下標的元素)。下面是一些例子:
@array = qw# dino fred barney #;
$m = shift (@array); #$m 得到“dino”, @array 現在爲(“fred”, “barney”)
$n = shift @array; #$n 得到”fred”, @array 現在爲(“barney”)
shift @array; #@array 現在爲空
$o = shift @array; #$o 得到undef, @arry 仍爲空
unshift(@array,5); #@array 現在爲(5)
unshift @array,4; #@array 現在爲(4,5)
@others = 1..3;
unshift @array, @others; #array 現在爲(1,2,3,4,5)

12. 默認變量
$_ = "default variable\n";
print;

foreach (1..10)
{
    print "I can count to default value $_\n";
}

13. context
@people = qw (dd cc bb aa);
print "people:\n@people\n";
@sorted = sort(@people);
print "sorted:\n@sorted\n";
$number = @sorted;
print $number."\n";

另一個例子是 reverse。在列表 context 中,它返回反轉的列表。在標量 context 中,返回反轉的字符串(或者將反轉的結果串成一個字符串):
@backwards = reverse qw / yabba dabba doo /;
#返回 doo, dabba, yabba
$backwards = reverse qw/ yabba
dabba doo /;
#返回 oodabbadabbay

讓我們看看已經出現過的一些別的表達式及其 context。下面是一些標量 context:
$fred = something;
$fred[3] = something;
123 + something;
something + 654
if(something){ ... }
$fred[something] = something;
下面是一些列表 context:
@fred = something;
($fred, $barney) = something;
($fred) = something;
push @fred, something;
foreach $fred(something)
sort something
reverse something
print something


@bamey = "this is ".' '."world";
foreach $s(@bamey)
{
    print $s."\n";
}  #結果爲: this is world

@arr = qw [bb cc aa ee];
print "I have ".@arr." arr\n"; #answer is: I have 4 arr
print "I have ",@arr," arr\n"; #answer is:I have bbccaaee arr
print "I have ", scalar @arr," arr\n";  #answer is: I have 4 arr


14. hash的定義使用
定義
my %some_hash = ("last_name", "kelvin", "first_name", "liu");
取值
$hash{$some_key}
賦值
$family_name{“ fred”} = flintstone;

#my %some_hash = ("last_name", "kelvin", "first_name", "liu");
my %some_hash = (
"last_name" => "kelvin",
"first_name" => "liu"
);
my @keys = keys %some_hash;
my @values = values %some_hash;
my @array = %some_hash;
print @array."\n"; #4
print "@array"."\n";  #first_name liu last_name kelvin
my $key;
my $value;
foreach $key(@keys)
{
    print $key."\n";
}
=cut

 
my %some_hash = (
"last_name" => "kelvin",
"first_name" => "liu"
);
my @keys = keys %some_hash;
my @values = keys %some_hash;
while ((my $key,my $value) = each %some_hash)
{
    print $key." and ".$value."\n";
}
foreach my $key2 (sort keys %some_hash)
{
    print "key = ".$key2.", value = ".$some_hash{$key2}."\n";
}
if (exists $some_hash{"first_name"})
{
    delete $some_hash{"last_name"};
    my @keys3 = keys %some_hash;
    foreach my $key4 (@keys3)
    {
        print "compare with $key4"."\n";
        if ($key4 eq "last_name")
        {
            print "this is $key4"."\n";
            exit;
        }
        print "$key4 not equals last_name\n";
    }
}

15. regular expression:正則表達式
點(.)是通配符, 它可以匹配任何單個的字符, 但不包括換行符(“\n”).
如果只希望點(.)匹配句號,可以使用反斜線。這條規則對 Perl 正則表達式中所有元字符均有效:
元字符前使用反斜線將使它變成普通的字符。如,模式/3\.14159/中的點(.)即不是通配符。

可以這樣看待星號(*): “前面的東西,重複任意次數,包括 0 次.只是前面 的一個字符,不是任意匹配。
將.*叫做“任意字符串匹配模式”,因爲任意的字符串均能被匹配上

因爲加(+)意指一個或多個,因此至少是一個。可以這樣看待加(+): “最後一項, (可選的)至少還 有一項。 ”

問號(?),其含義是前面一個項出現一次,或者不出現。也就是說,前面這個項出現 1 次或者 0 次,此外不會有其它情況。因此,/barm-?bamm/只匹配:bamm-bamm 或 bammbamm。這很容易記住: “前面 的這個項,出現?或者不出現?”

模式/(fred)+/能匹配上像 fredfredfred 這樣的字符串, 這更可能是你所希望的。 那麼模式/(fred)*/ 呢?它將匹配上像 hello,world 這樣的字符串◆。

任何數字的類,[0-9],可以被簡寫爲:\d。
if(/HAL-[0-9]+/){
print “ string mentions some model of HAL computer.\n”
The
;
}
例子可以被寫作/HAL-\d+/。
\w 被稱作 “ word’ 字符:[A-Za-z0-9_]。
\w 不能匹配單詞,而只能匹配單個字符。爲了匹配整個單詞,需要後接加號。模式 /fred \w+ barney/將匹配 fred,空 格,一個“單詞(word) ,然後是空格和 barney。因此,如果 fred 和 barney 之間有一個單詞◆,由單個空格分隔開,它將 ” 能匹配上。

\s 對於匹配空白(whitespace)將非常方便。它等價 於[\f\t\n\r ],其含 5 個空白字符:格式符(form-feed) ;製表符(tab),換行符,回車,以及空格符。

希望得到這三種簡寫形式的補集。如果那樣的話,你可以使用[^\d], [^\w], 和[^\s],其含義分別是,非數
字的字符,非 word(記住我們對 word 的定義)的字符,和非空白的字符。也可以使用它們對應的大寫形式:\D, \W, \S 來 完成。它們將匹配它們對應的小寫形式不能匹配上的字符。

/i
要創建一個大小寫無關的模式,如匹配 FRED 時,也能匹配上 fred, Fred,可以使用修飾符 /i:
if(/yes/i) {#大小寫無關
print “ that case, I recommend that you go bowling.\n” ;
}

/s
可以使用/s 這個修飾符。它將模式中點(.)◆的行爲變成同字符類[\d\D]的行爲類似:可以匹配任何字符,包括換 行符。
$_ = “ saw Barney\ndown at the bowing alley\nwith Fred\nlast night.\n” ;
if(/Barney.*Fred/s){
print “ That string mentions Fred after Barney!\n” ;
}
如果不使用/s,那麼上述模式將不能被匹配上,因爲這兩個字符不在同一行中。

/x
/x 修飾符,允許你在模式中加入任何數量的空白,以方便閱讀:
/-?\d+\.?\d*/ #這是什麼含義?
/ -? \d+ \.? \d* /x #要好些
由於/x 允許模式中使用空白,那麼模式中的空格,製表符將被忽略。可以在空格前加上反斜線或者使用\t(許多方法中的一 種) ,但匹配空白更常用的方法是使用\s(\s*或\s+)。
Perl 中,註釋可以被作爲空白,因此使用/x,可以在模式中加上註釋:
/
-?
#可選的負號
\d+ #小數點前一個或多個十進制數字
\.? #可選的小數點
\d* #小數點後一些可選的十進制數字
/x
#模式結束

^ and $:開始結尾匹配
符號^(脫字字符◆)表示在字符串的開頭進行匹配,而符號$則表示在結尾◆。因此,模式/^fred/只匹配字符串的開頭部分; 它不會匹配上 manfred man。而/rock$/只在結尾處匹配;其不會匹配上 knute rockne。

一個經常使用的例子是/^\s*$/,它將匹配一個空行(blank line) 。這 裏的“ blank(空白)” ,可以是空白符,如製表符,空格等,它們是不可見的。

錨定不僅僅針對字符串的兩頭。詞界錨定,\b,是針對單詞使用的。如/\bfred\b/可以匹配上單詞 fred,但不能匹配 frederick, alfred, man fred mann。這同字處理軟件中的 “ 全字匹配(match whole words only)”
是類似的。

非詞界錨定爲\B。它將在任何非\b 匹配的點上進行匹配。因此,模式/\bsearch\B/將匹配 searches,searching, searched, 但不能 匹配 search,或者 researching。

對$_進行匹配只是默認的行爲,使用綁定操作符(=~)將告訴 Perl 將右邊的模式在左邊的字符串上進行匹配,而非對$_匹配。 例如:
my $some_other = “dream of betty rubble.”;
if($some_other =~ /\brub/){
print “ Aye, there’ the rub.\n” ;
}

匹配上的那部分字符串將自動存儲在$&之中。
$`中含有正則表達式引擎在匹配成功前所找到的變 量,而$'爲此模式還沒有匹配的剩餘部分。如果將這三個變量放在一起,你將得到原始字符串:

模式/a{5,15}/將匹配 5 個到 15 個 a 中的任意一個(包括 5,和 15) 。如果 a 出現了 3 次,則次數太少,而不能匹配上;
如果省略掉第二個數字(逗號留下) ,現在沒有上限了。
如果除了上限數字外,逗號也被省略了,那將匹配確定的次數.
星號(*)等同於{0,},表示 0 個或多個。加號(+)等同於{1,},表示 1 個或多個。而問 號(?)則等同於{0,1}。


16. 循環控制語句
Last:
last 會立刻結束循環。(這同C 語言或其它語言中的“break”語句類似)。它從循環塊中“緊急退出”。當執行到last,循環即結束,如下例:
#輸出所有出現fred 的行,直到遇見_ _END_ _標記
while(<STDIN>){
if(/_ _ END_ _/){
#這個標記之後不會有其它輸入了
last;
}elsif(/fred/){
print;
}
}
##last 跳轉到這裏##

next:
有時還不希望結束循環,但本次循環已經結束。這種情況下,next 是非常適用的。它跳到當前循環塊的最後面(塊內)◆。
next 之後,又會進入下一輪循環(這和C 或者類似語言的“continue”相似):
#分析輸入文件的單詞
while(<>){
foreach(split){ #將$_分拆成單詞,並依次賦給$_
$total++;
next if/\W/; #不是“words”的被跳過
$valid++;
$count{$_}++; #對每個單詞進行計數
##next 跳到這裏##
}
}
print “total things = $total, valid words = $valid\n”;
foreach $word (sort keys %count){
print “$word was seen $count{$word} time.\n”;
}

redo:
循環控制的第三個操作是redo。它會調到當前循環塊的頂端,不進行條件表達式判斷以及接着本次循環。(在C 或類似語言中沒有這種操作。)下面是一個例子:
#輸入測試
my @words = qw{ fred barney pebbles dinoWilma 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; #跳轉到循環頂端
}
}
print “You’ve completed the test, with $errors errors.\n”

三元操作符:?
my $size =
($width < 10 ) ? “small”:
($width < 20) ? “medium”:
($width < 50) ? “large”:
“extra_large”; #default

發佈了32 篇原創文章 · 獲贊 4 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章