perl學習筆記1

myownstars發表於2011-07-27
如何debug一個perl程式
--5.6版本或更高,
#!/user/bin/perl –w
Use warnings;--此時會報告編譯錯誤,但不會終止程式執行
Use diagnostics;--檢視更詳細的診斷說明,但程式會啟動很慢(向記憶體中載入警告和詳細說明)

$ perl –M diagnostics ./my_program—避免每次都載入記憶體,比較方便,直接顯示錯誤資訊


單引號與雙引號的區別
單引號—除了單引號和反斜線字元,所有字元都代表自己;標示反斜線字元本身,需要在其前面再加一個反斜線;
‘hello world\n’—輸出hello world\n
'hello'\\n'—會報錯Backslash found where operator expected at test.pl line 1, near "'hello'\"
print 'hello\'\\n' –輸出hello'\n
雙引號
--\代表跳脫字元
“hello world\n”—輸出hello world,後面緊接換行符

如何連線字串
採用’.’--”hello ”.”world”等同於”hello world”
“justin” X 3—等同於”justinjustinjustin”


獲取使用者輸入
--,獲取使用者行輸入,會等待
$line = ;
If ($line eq “\n”) –使用者輸入換行符,

Chomp
--去除行尾的換行符
Chomp($text = )等同於 $text =; chomp($text);

Qw
--建立字串列表,不必輸入引號;
Qw( fred barney betty dino )也可以qw< a b c >或qw# qa qb qc #
($a[0], $a[1], $a[2], $a[3]) = qw/a b c d/;
@a = qw/ a b c d /;

POP/PUSH運算子
@array = 5..9;
$a = pop(@array);--@array為(5,6,7,8),$a為9
Pop @array;--@array現在是(5,6,7)
Push(@array,0)--@array現在是(5,6,0)

Shift/unshift運算子
@a = qw# dino fred barney #;
$m = shift(@a);--$m為dino,@a為(“fred”,”barney”)
Unshift(@a, ‘asd’);--@a現在為(“asd”,”fred”,”barney”)

字串陣列內插
@a = qw( a b c);
$email = “fred@a.edu”—則會內插@a陣列
應寫為
$email = “fred\@a.edu”或者$email = ‘fred@a.edu’;

Foreach控制結構
@rocks = qw/ bed slate lava /;
Foreach $rock (@rocks) {
 $rock = “\t$rock”;
 $rock .= “\n”;
}
迴圈結束後,控制變數會恢復成迴圈執行之前的值

$_ “老地方” 預設變數
--當未告知perl使用哪個變數視,自動使用$_
Foreach (1..10) {
  Print “ I can count to $_ \n”;
}

$_ = “Yahoo \n”;
Print;--預設列印$_

Reverse
--讀取列表的值,並按相反的次序返回該列表
@a = 6..10;
@a = reverse @a;-- 此時a的值10,9,8,7.6
Reverse @a;-- 語法錯誤


Sort
--讀取列表的值,並且根據內部的字元編碼的順序,進行排序;對ASCII編碼的字串,則按ASCII碼排序
@rocks = qw/ a b c d /;
@rocks = sort @rocks; --排序後為a b c d


標量上下文/列表上下文
--列表上下文產生元素的列表;標量上下文則會返回陣列中元素的個數
@a = qw( d z a );
@b = sort @a;--列表上下文a,d,z
$n = 42 + @a;--標量上下文:42 + 3,得45
@backward = reverse qw / a d c/--變成a,c,d
$backward = reverse qw / a d c/--變成cda,標量上下文
$fred = somethind;--列表上下文
($fred) = somethind;--標量上下文

清空陣列
@betty = ( );
@betty = undef;--得到一個列表,且僅有一個元素;清空失敗

強制指定標量上下文
--在列表上下文的地方,強制引入標量上下文,可以使用偽函式scalar
@rocks = qw( a b c d );
Print “ I have “, @rocks,” rocks \n”;--輸出各種石頭的名稱
Print “ I have “, scalar @rocks, “ rocks \n”;--輸出石頭的數量

列表上下文中的
--標量上下文中返回輸入資料的下一行;列表上下文中返回所有剩下的行,直到檔案結尾,從鍵盤輸入的按control-D標示檔案結尾;
@lines = ;--列表上下文讀取標準輸入
Chomp(@lines);--
Chomp(@lines = );--讀入所有行,且去除換行符

一次讀入的是400M的日誌檔案,perl會全部讀入,會佔用至少1G的記憶體,因為perl通常浪費記憶體來節省時間;



子程式
--使用sub定義,可以在程式的任何地方
--可以在任意表示式中使用子程式名,用&呼叫
--子程式最後一次運算的結果會被自動當成返回值
$n = &max(10.15);
引數列表被傳入子程式,陣列變數為@_,在子程式執行期間有效;子程式的第一個引數儲存於$_[0],第二個為$_[1];
--私有變數
Sub max {
  My($m,$n);--私有變數
  ($m,$n) = @_;
  If ($m > $n) {$m} else {$n}
}
--限制長度可變的引數列表
Sub max{
  If (@_ != 2) {
Print “ &max should get exactly 2 arguments \n”;
  }
}
--更好的&max子程式
--採用high-water mark演算法
$maximum = &max(3,5,10,6,4);
Sub max {
  My($max_so_far) = shift @_;--將陣列中的第一個值,暫時當做最大值
  Foreach (@_) {--遍歷陣列中的其他元素
If ($_ > $max_so_far) {
  $max_so_far = $_;
}
  }
$max_so_far;
}
非標量返回值,可以返回列表值
--想取出某段範圍的數字
Sub list_from_fred_to_barney {
  If ($fred < $barney) {
$fred..$barney;
  } else {
  #從$fred倒數回$barney
  Reverse $barney..$fred;
  }
}
$fred = 11;
$barney = 6;
@c = &list_from_fred_to_barney;--@c的值為(11,10,9,8,7,6)

持有性私有變數
--使用state宣告變數,子程式可以多次保留變數
--任意型別的變數都可以被宣告為state變數
Sub marine {
  State $n = 0;
  $n += 1;
  Print “Hello, sailor number $n \n”
}

Running_sum(5,6);
Running_sum(1..3);
Sub running_sum {
  State $sum = 0;
  State @numbers;
 
  Foreach my $number (@_) {
Push @numbers, $number;
$sum += $number;
  }
 
 Say “The sum of (@numbers) is $sum”;
}
輸出
The sum of (5,6) is 11;


標準輸入
--作為行輸入,讀取到檔案結尾,會返回undef,自然會跳出迴圈
--while (defined($line =)) { print “I saw $line”;};
鑽石運算子<>
--行輸入運算子特例,
--while (defined($line = <>)) { ….};
呼叫程式./my_program fred betty,則會依次讀入檔案fred/betty中的內容;切換檔案時候中間不會有間斷;
--<>的引數來自@ARGV陣列,由perl直譯器建立的,與普通陣列使用一樣;
--呼叫引數



標準輸出
Print @array;--一個接一個的列印出資料中元素,之間沒有空格
Print “@array”;--列印字串,以空格間隔
Print (2+3)*4;--輸出5;接著perl從print取得返回值1,再將它乘以4;

格式化輸出printf
%g—按需要自動選擇浮點數、整數或指數
%d—顯示整數,舍掉小數點
%s—字串;printf “%10s\n”, “Wilma”輸出     Wilma;
%%--輸出百分號;printf “%.2f%%”;輸出0.00%
輸出陣列
my @item = qw { justin abc  dbc asdg };
printf "The itme are:\n".("%10s\n" x @item),@item;
輸出—括號中的@item是標量上下文,而後面的是列表上下文
The itme are:
     justin
       abc
       dbc
      asdg

檔案控制程式碼
--程式裡代表perl與外界之間I/O聯絡的名字,建議名字全部大寫
--6個保留名:STDIN、STDOUT、STDERR、DATA、ARGV、ARGVOUT
./my_program Wilma—程式的輸入檔案來自檔案dino,輸出到檔案wilma
Cat fred barney | sort | ./my_program | grep something |lpr
--將檔案fred和barney中的內容輸出並排序,然後輸入到perl程式,執行完再過濾出需要的結果併傳送到印表機列印

開啟檔案控制程式碼
Open CONFIG, “dino”;
Open CONFIG, “Open CONFIG, “>dino”;--開啟檔案並向其寫入資訊,寫之前清空原有資訊
Open CONFIG,”>>dino”;--開啟檔案並向其追加資訊
可以使用任何的標量表示式
My $file = “my_output”;
Open LOG, “> $file”;--中間有空格,避免檔名中出現’>’,導致>變成>>;
不正確的檔案控制程式碼
My $success = open LOG, “>>logfile”;
If (! $success){ ..open操作失敗}

用die處理嚴重錯誤
--當程式遭遇到嚴重錯誤時,die函式會輸出指定的資訊到標準錯誤流中,並讓程式立即終止,並返回不為0的退出碼;
If (! Open LOG, “>>logfile”) {
  Die “Cannnot create logfile:$!”;--$!是可讀的系統出錯資訊
}

使用warn輸出警告資訊
--功能與die類似,但不會終止程式執行

改變預設的檔案輸出控制程式碼
--不顯示指定,預設輸出到STDOUT
Select BEDROCK;--接下來的print/printf將向BEDROCK控制程式碼中輸出資訊
--資料輸出到檔案控制程式碼時,預設都會經過緩衝處理;$| = 1;#立即重新整理緩衝區

複用標準檔案控制程式碼
--開啟已經被開啟過的檔案控制程式碼,包括6個標準檔案控制程式碼
--open STDERR, “>> /home/oracle/.error_log”

Say
--等同於print,但行尾自動加上換行符
--輸出內插陣列,仍需要用引號括起來,否則陣列中的元素會連成字串
My @array = qw( a b c d);
Say @array;--輸出abcd\n
Say “@array”;--輸出a b c d\n


雜湊
--$hash($some_key);賦值$family_name(“fred”) = “bac”; $file = $family_name(“fred”);不存在的值會得到undef;
--%訪問整個hash;
%some_hash = (“foo”,35,”bar”,2.5); 也可使用直觀的胖箭頭 my %last_name = ( “fred” => “flintstone”, “dino” => undef);
--賦值給陣列 @array = %some_hash;但是排列順序可能會變
--%new_hash = %old_hash;%inverse_hash = reverse %any_hash發轉hash

Keys/values函式
--my %hash =(“a” => 1,”b” => 2,”c”=> 3);
--my @k = keys %hash;--a,b,c
--my @v = values %hash;--1,2,3
--在標量上下文中,這兩個函式都會返回雜湊中鍵/值對的個數,計算過程不必對整個雜湊進行遍歷
My $count = keys %hash;--得到3

Each函式
--羅列雜湊的每個鍵/值對
While ( ($key,$value) = each %hash ) {
  Print “$key => $value\n”;
}
--each返回鍵/值的順序是亂的,如果需要依次處理雜湊,對鍵排序
Foreach $key ( sort key %hash ) {
  $value = $hash($key);
  Print “$key => $value\n”;或者print “$key => $hash($key)\n”;
}

Exists函式
--檢查雜湊中是否有某個鍵
If ( exists $books(“justin”) ) {…..}

Delete函式
--從雜湊中刪除指定的鍵及其相對應的值
My $person = “justin”;
Delete $books($person);

%ENV雜湊
--雜湊獲取執行環境變數,存取%ENV雜湊
$ENV(PATH)



正規表示式 regular expresssion
簡易模式
$_ =  “yabba dabba doo”;
If (/abba/) {…..} –表示式/abba/會在$_中尋找這4個字元組成的串,如果找到就返回真
/cake\tsprite/ --會匹配cake、一個製表符和sprite

元字元
--點號(.)配置任何單字元,換行(“\n”)除外
--反斜線(\),在任何元字元前面加上反斜線,就會使他失去元字元的作用;要得到真正的反斜線,用兩個反斜線表示;/3\.1415926/得到3.1415926

簡易量詞
--星號(*)配置前面內容0次或多次的 /fred\t*barney/匹配fred和barney之間有任意多個製表符的串
--(.*)匹配任意字元無限多次,/red.*barney/
--(+)加號,匹配前一個條目一次以上:/fred +barney/
--(?)問號,前一個條目可以出現一次或不出現

模式分組
--()表示分組;/fred+/表示freddddd,/(fred)+/匹配fredfredfred
--反向引用;\1、\2,
$_ = “abba”;
If (/(.)\1/) {…}—圓括號中的點號匹配任何非回車字元,則同’bb’匹配
If(/y(….)d\1/) {..}—匹配y後面連續4個連續的非回車字元,並且用\1在d字元之後重複這4個字元
其中\n代表第n組括號,從左往右
$_ = "yabba";
if (/(.)(.)\2\1/) {
  print "$_ matches\n";--匹配
}
$_ = “AA11BB”;
If(/(.)\111/) {…}; --此時搜尋第111個括號會失敗
If( /(.)\g{1}11/ ) {…};--搜尋第一個括號且後面跟上11

擇一匹配
--豎線(|),左邊或右邊匹配都行;/fred|barney|betty/匹配任何含有fred或barney或betty的字串;
--/fred( |\t)+barney/匹配fred好barney之間空格、製表符或兩者組合出現一次以上的字串,加號表示重複一次或多次
--/fred( +|\t+)barney/,兩個單詞間一定全是空格或製表符

字符集
--寫在方括號[]中,只匹配單個字元,可以是字符集中列出的任何一個
--[a-zA-Z]匹配52個字母中的任何一個
--脫字元^,表示排除在外;[^n\-z]匹配n、-、z以外的任何字元,-前面加反斜線標誌轉義

字符集簡寫
--\d代表[0-9];\w表示單寫字元[A-Za-z0-9];
--\s相當於[\f\t\n\r ],即換頁、製表、換行、回車以及空格,但只是匹配其中一個字元,可以寫成\s+匹配一個以上;
--\h匹配橫向空白,即[\t ];\v匹配縱向空格,[\f\n\r];\R匹配任何型別的斷行

反義簡寫
--\d、\w、\s的反義簡寫就是\D,\W.\S,也可寫成[^d],[^w],[\s]
--/[\dA-Fa0f]+/匹配16進位制數字
--[\d\D]表示任何數字或非數字,即匹配任何字元(而點號匹配換行符以外的任意字元);[^\d\D]


以正規表示式進行匹配
以m//進行匹配
--//為其簡寫;/^http:\/\//匹配起始的http://,也可以寫成m%^http://%

/i進行大小寫無關的匹配
Chomp($_ = );
If (/yes/i)—大小寫無關的匹配

/s匹配任意字元
--點號無法匹配換行符,而/s可以完成這個任務;它將模式中的每個點號按[\d\D]處理
$_ = “I saw Barney\ndown at the bowling allay\n”;
If (/Barny.*fred/s)—

/x加入空白
--能夠在模式裡面隨意加上空白,更易閱讀;
--/-?\d+\.?\d*/可以改寫成/ -? \d+ \.? \d* /x,使原始的空白與製表符失去意義;如果還要匹配空白與製表符,就得在前面補上一個反斜線字元;

組合選項修飾符
--在一個模式中使用多個修飾符,可以連在一起使用,先後順序不會影響匹配的結果
If (/barney.*fred/is) {…}
同樣的模式加上註釋之後
If (m{
  Barney#小夥子 barney
  .*    #之間的任何東西
  Fred  #大嗓門的fred
  }six)  #同時使用/s,/i和/x

錨位
--預設情況,模式匹配的過程開始於待匹配字串的開頭,若不相符就一直往後推移;錨位可以讓模式直接匹配字串的某處
--脫字元^,表示字串開頭;美元符號$表示字串結尾;
--/^\s*$/用來匹配空白行,如果不加前後兩個錨位,則會把非空白行也一起算進去;

單詞錨位
--錨位不侷限於字串的首尾;\b匹配單詞邊界
--/\bfred\b/只能匹配fred,無法匹配frederick/alfred,此處的單詞指一連串的字母、數字與下劃線的組合,也就是匹配/\w+/模式的字元;
--非單詞邊界錨位是\B,能匹配所有\b不能匹配的位置;/\bsearch\B/會匹配searches、searching,但不匹配search、researching;

繫結運算子=~
--預設情況下模式匹配物件為$_,而=~能讓perl拿右邊的模式匹配左邊的字串,而非$_;
My $some_other = “I dream of betty rubble”;
If($some_other =~ /\brub/) {…}
也可以寫成如下方式:
Print “Do you like Perl?”;
My $like_perl = ( =~ /\byes\b/i);--判斷回答是否為yes,不區分大小寫
If ($like_perl) {…}

模式串中的內插
My $what = shift @ARGV;
While (<>) {
  If (/^($what)/) {--定位於字串的開頭
--如果第一個命令列引數是fred|barney,則模式會變成/^(fred|barney)/,即在每一行開頭尋找fred或barney

捕獲變數
--一個圓括號代表一個變數,用$1、$2表示
--失敗的匹配模式不會改動上次成功匹配時捕獲的內容
$_ = “Hello there, neighbor”;
If (/(\S+) (\S+), (\S+)/) {
  Print “$1 $2 $3”;--列印出Hello there neighbor
}
My $dino = “I fear that I’ll be extinct after 1000 years.”;
If($dino =~ /(\d*) years/) {…}
--不捕獲模式,允許使用括號但不作捕捉;書寫的時候需要在左括號的後面加上?:(問號和冒號);
If (/(?:bronto)?saurus (steak|burger)/) {—不捕獲括號跳過bronto
 Print “Fred wants a $1\n”;
}

命名捕捉
My $names = ‘Fred or Barney’;
If ( $names =~ m/(\w+) and (\w+)/ )—不會匹配
If ($names =~ m/(\w+) (and|or) (\w+)/)—可以匹配
  Say “$1, $2”;--輸出Fred or,而Barney進入了$3
--而命名捕捉會把結果放進一個特殊的雜湊%+,其中的鍵就是在捕捉時候使用的特殊標籤,值就是被捕獲的串;
--為捕獲串加標籤,(?

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15480802/viewspace-703261/,如需轉載,請註明出處,否則將追究法律責任。

相關文章