Perl 的特殊變數 $`, $', $1..$9, $#陣列名
介紹幾個PERL比對會用到的變數。
$`和 $'
這兩個特殊變數會用在比對的時候,Perl 的特殊變數:$_ 、$+、 $&、$! 提到 $& 代表比對範圍內的全部結果,有時想要取出的並不是比對本身的字串,而是比對目標前和後的字串,這時就需要這兩個特殊變數,非常的方便:
$` 代表比對範圍之前的字串,那個 '`'是反單引號,一般而言是數字1左邊的那個鍵。
$' 代表比對範圍之後的字串。
來看範例:
$str="a running dog "; if( $str =~ /ing/){ print "\$`=$`\n"; print "\$&=$&\n"; print "\$'=$'\n"; }
結果
$`=a runn
$&=ing
$'= dog
第3行 $`取出ing前面的字串
第4行 $&取出ing本身比對結果的字串
第5行 $'取出ing後面的字串,注意dog前的空白也算。
這個變數在切文章時很有用,可以參考這篇PERL一次讀取檔案所有內容的方法($/)。
$#array_name
這個變數是由 "$#" 和陣列的名稱所組成,作用是取得陣列最後一個值的索引。
由於陣列索引由0開始,所以陣列的項目數量就是這個特殊變數值再加上1,例如
陣列 @arr=(1,2,3); 則$#arr=2;
陣列的項目數量就是2+1=3,
因此這個變數主要的作用就是計算陣列的長度。
但是這個變數怪異的地方在於他是可以寫入值。
例如 陣列 @arr=(1,2,3); 則$#arr=2;
如果我們把 $#arr=1; 那麼就會讀不到 $arr[2]的值(不會報錯)。
相反的,如果把$#arr=3; 陣列就自動會變大,但是讀取 $arr[3] 會得到空的結果。
$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 …
$1..$10 這幾個特殊變數在比對中常會用到,也就是比對的第n個結果,他的順序是由左算起來第幾個小括號來決定。
我們來看一下範例,例如下面的記錄字串,我一共用了10個括號分別包起來:
$doc="<188>Nov 18 02:34:56 這是一隻豬"; if( $doc =~ /^<(\d+)>(((\w+) (\d+)) ((\d+):(\d+):(\d+))) (.+)$/){ print "\$0=$0\n"; print "\$1=$1\n"; print "\$2=$2\n"; print "\$3=$3\n"; print "\$4=$4\n"; print "\$5=$5\n"; print "\$6=$6\n"; print "\$7=$7\n"; print "\$8=$8\n"; print "\$9=$9\n"; print "\$10=$10\n"; }
執行結果
$1=188
$2=Nov 18 02:34:56 <==左邊算來第2個左刮號,以此類推
$3=Nov 18
$4=Nov
$5=18
$6=02:34:56
$7=02
$8=34
$9=56
$10=這是一隻豬
如果刮號超過10個就繼續寫 $11 $12 .... 但我不知道可以寫到多少?
上例中只有10個刮號,如果印 $11 會出現什麼?讓你失望了,只是一個空值而已。
\1 \2 \3 .. \9 \10 ...
上面錢號帶著數字的特殊變數如果把 '$' 換成反斜線 '\' 的話,就是$1 $2 $3 ..$9 $10 的替代型。
使用時機就是把比對的結果再拿進去比對的情況。
換句話說,就是把符合比對的結果再丟入比對。來看以下範例,我想找出連續兩個一樣的字母,例如 good, tee, jaff , 要怎麼寫?
上面的範例是不正確的,因為他沒把連續出現的字母表達出來,他的意思只是 A-Za-z 裡面52個字母連續出現二個的意思。
因此改寫成:
那麼只要刮號中的任一個字母出現後,後面用\1代表又重覆這個字母,就能找出比對的結果。
這樣就會是正確的結果了,請自行試試看吧。
後記
這篇文章寫了三年,當初沒一口氣寫完,本來想作廢後來還是整理出來…