Perl 命令行一句話代碼 翻譯+總結


編輯/整理:523066680@163.com
首發:[連載]Perl 命令行一句話代碼,翻譯+整理

序:內容取自 《Perl One-Liners》,注意該教程中示例的 ' 符號(單引號)在windows 中應改為雙引號,否則不會奏效。我在翻譯和摘錄的代碼中也會改用雙引號

備注:

  1. 不做全文翻譯,盡量簡明
  2. 假設看官已經有正則表達式基礎
  3. 環境:Win7, Strawberry Perl 5.24 Portable Edition

Chapter 1 - Perl ONE-LINERS

第一個示例,全局將文件中的 you 替換為 me:

perl -pi -e "s/you/me/g" file

/g 表示全局替換
-e 參數允許執行 Perl 代碼
-p 參數確保處理文本的每一行並且將處理后的結果打印出來
-i 參數將修改的結果應用到文件中(所以看不到 -p 打印的內容了)
-i[extension] edit <> files in place (makes backup if extension supplied)

注意,實際測試 -i 參數必須提供擴展名以備份文件,否則提示:Can't do inplace edit without backup.
perl -pi.bak -e "s/you/me/g" file

處理多個文件:

perl -pi.bak -e "s/you/me/g" file1 file2 file3

僅處理含有"we"的行:

perl -pi.bak -e "s/you/me/g if /we/" file

打印文件中重復出現的行:

perl -ne "print if $a{$_}++" file

$_ 表示當前遍歷的行的內容
-n 表示遍歷所有行(類似 -p 但不負責打印結果)

執行后將自動建立字典 %a,當 $_ 對應的值第一次出現的時候,$a{$_} 還是 undef(同0),+1在下次生效。再次出現時為1,打印輸出,以此類推。

添加並打印行號:

perl -ne "print \"$. $_\"" file

在 Perl 中,$. 是一個特殊變量,表示當前行數。這個例子也可以改用 -p
perl -pe "$_ = \"$. $_\"" file

帶行號,但僅顯示重復行

perl -ne "print \"$. $_\" if $a{$_}++" f.txt

借用 List::Util 模塊統計每行中出現的數字的和

perl -MList::Util=sum -alne 'print sum @F' f.txt

說明:
-MList::Util 導入 List::Util 模塊
=sum 表示導入 List::Util 的 sum 函數
-a 參數,自動按空格划分行的內容並保存到 @F,使單詞、數字獨立出來
注 -F/pattern/ 參數可指定其他划分規則
-l 參數確保每一次輸出都換行,省了手動 "\n"

讓時間回退到 1299 天前:

perl -MPOSIX -le "@t = localtime; $t[3] -= 1299; print scalar localtime mktime @t"

實際時間:
Wed Apr 26 19:31:22 2017
輸出:
Sat Oct 5 19:31:22 2013

這個過程實際就是 用 @t 獲取 localtime 的返回結果(數組環境),將日期減1299(在數組成員中會變成負數),再使用 mktime 將其封裝,返回給 localtime,再用標量環境打印 localtime 的返回值

如何生成8位隨機字符密碼?map 走起:

perl -le "print map { ('a'..'z')[rand 26] } 1..8"

1..8 產生數組數字從 1-8,關鍵是產生8次循環
('a'..'z') 產生數組元素a-z,而 [rand 26] 隨機產生數組下標,也就是隨機選取字母
map 返回每一次循環的處理結果

要我寫的話可能會用 grep ,逐個 print
perl -e "grep { print (('a'..'z')[rand 26]) } (1..8)"

發現 print ('a'..'z')[rand 26] 會提示語法問題,必須外加括號。

累計文本中每行的首列數字的和

perl -lane "$sum += $F[0]; END { print $sum }" f.txt

END {} 定義了一個代碼塊,該代碼塊在腳本結束時運行

如果對 perl 的任一項參數有疑惑,可以參考
perldoc perlrun

其他參考

perldoc perlvar - 關於 Perl 的特殊變量
perldoc perlop - 操作符
perldoc perlfunc - 函數

Chapter 2 - 換行和間隔符

在每行的末尾增加空白行

perl -pe "$\=\"\n\"" f.txt

之前對 -p 和 -e 參數做過簡要的說明,以上代碼相當於:

while (<>) {
    $\ = "\n";
} continue {
    print or die "-p failed: $!\n";
}

構成

-p 參數建立 while (<>) {} continue { print } 循環結構
在 while 循環內默認用 $_ 存儲當前讀入的行,而 print 的缺省參數為 $_

-e "代碼" 對應 while 循環內的代碼。

continue 語句塊在 while 的每次循環末尾繼續執行,
特點是 continue {} 的代碼不會因為 next 而跳過

特殊變量 $\ 相當於 AWK 中的 ORS 變量 (Output Record S eparator) 。
$\ 的內容將自動追加到 $_ 的末尾。循環地為 $\ 賦相同的值是不必要的,
將其放在 BEGIN 代碼塊可以節省開銷(BEGIN代碼塊優先執行):
perl -pe "BEGIN { $\=\"\n\" } " f.txt

相當於:

BEGIN { $\ = "\n" }
while (<>) {
} continue {
    print or die "-p failed: $!\n";
}

其他方案

通過 "." 操作符添加換行:
perl -pe "$_ .= \"\n\"" f.txt

或者使用s///正則替換:
perl -pe 's/$/\n/' f.txt

甚至可以利用 say 操作符的特性(Perl 5.10 或以上):
perl -nE 'say' f.txt

-E 參數允許打開所有 Perl 的可選特性(為了支持 say 操作符)
-n 參數類似 -p ,遍歷所有讀入的行但不主動 print(前面介紹過了)
say 操作符類似 print,但 say 總是在每行的末尾添加 "\n"

最后,別忘了多用 perldoc, 執行 perldoc perlrun 查看perl命令行參數的詳細說明

換行加倍,空行除外

perl -pe "$_ .= \"\n\" unless /^$/" f.txt

unless 在 perl 中是 if not 的意思
/^$/ 表示行的開頭和末尾之間沒有其他字符

也可以用 \S 篩選:
perl -pe "$_ .= \"\n\" if /\S/" f.txt

\s 代表一系列空白符號
\S 表示空白以外的字符
如果一行中包含空給以外的字符,則追加 \n

三倍換行符

相信各位已經能舉一反三,不解釋了(后面的命令行示例省去文件名部分)
perl -pe "$\ = \"\n\n\""

perl -pe "$_ .= \"\n\n\""

perl -pe "s/$/\n\n/"

N倍換行符

Perl 使用 "字符"x數字 的方式對字符串翻倍疊加,例如7個換行符:"\n"x7

在每行之前添加空行

使用正則替換向文件開頭插入\n:
perl -pe 's/^/\n/'

刪除空白行

perl -ne 'print unless /^$/'

由於這里要自己判斷(篩選)輸出,所以使用 -n 而非 -p


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM