2025年1月8日 星期三

Perl one-liner 中 -MO=Deparse 參數--反向剖析功能

 以上回的指令為例,加上 -MO=Deparse  參數,產生如下輸出

>perl -MO=Deparse -0777 -ne "$temp=$1 and $temp=~s/\n//g and print $temp while /(?s)--- -- --(.+?)---/g" abc.ini

BEGIN { $/ = undef; $\ = undef; }

LINE: while (defined($_ = readline ARGV)) {

    $temp = $1 and $temp =~ s/\n//g and print $temp while /(?s)--- -- --(.+?)---/g;

}

-e syntax OK

這個選項在除錯時滿有幫助的,例如,我們可以用分號代替 and 關鍵字看看結果

>perl -MO=Deparse -0777 -ne "$temp=$1 ; $temp=~s/\n//g ; print $temp while /(?s)--- -- --(.+?)---/g" abc.ini

BEGIN { $/ = undef; $\ = undef; }

LINE: while (defined($_ = readline ARGV)) {

    $temp = $1;

    $temp =~ s/\n//g;

    print $temp while /(?s)--- -- --(.+?)---/g;

}

-e syntax OK

其中 $1 還沒被定義就使用了,在執行期會發生錯誤。




2025年1月2日 星期四

以 perl one-liner 對多行文字檔進行跨行比對,印出相符字串

先講結論。abc.ini為輸入檔,要比對--- -- --開頭、---結尾的字串,允許跨行。一行以蔽之:

perl -0777 -ne "$temp=$1 and $temp=~s/\n//g and print $temp while /(?s)--- -- --(.+?)---/g" abc.ini

之前遇到這種問題都會用暫時變數記一堆狀態來解決,昨天突發奇想,找到一些參數,沒想到也能一行解決。簡單來說就是兩個技巧的連續技。

第一個技巧是 -0777 參數, 參 Slurp a file from the command line with -g – The Effective Perler ,如果 perl 是 5.36 以後的版本,也可以直接下 -g 參數即可。顧名思義就是把輸入檔串成一個字串。

第二個技巧是 (s?) 開關, 參 Perl regex match string including newline - Stack Overflow  ,其作用是讓 DOTALL 開關打開,使單字元萬用比對符納入換行符號。

其它的小變化有二,一是 while 的使用,因為你把資料串成一行了,-ne 中幫你做的 while 就沒有原來的迴圈效果了,因此要手動加上;二是 /g 開關要加上,理由同上。

額外的變化有二, (.+?) 是讓比對不要貪心(greedy),$temp 是把結果的換行字元取代掉。

又是一個充實的補丁日呢~~