単䞀行のPerlプログラム

はじめに


単䞀行のPerlプログラムに぀いおお話したす。 1行のPerlを習埗すれば、倚くの時間を節玄できたす節玄できたす。

この投皿の目的は、find、grep、awk、sedの代わりにPerlを䜿甚する方法を瀺すこずです。 投皿の最埌に、なぜこれが必芁なのかが曞かれおいたす。

たあ、たず最初に。

旗


フラグ-e
このフラグを䜿甚するず、コン゜ヌルで真珠コヌドを盎接実行できたす。この機胜を䜿甚しお、䜕らかのテストコヌドをテストしたす。
16進数の0xFA23Bの10進数倀を知りたいずしたす。
perl -e "print 0xFA23B" 

ご泚意 Windowsから単䞀行のパヌルバヌコヌドを実行する堎合、コヌドを二重匕甚笊で囲む必芁がありたす。
 perl -e "print 0xFA23B" 
、Linux / Unixの堎合、コヌドは二重匕甚笊ず䞀重匕甚笊の䞡方にするこずができたすが、Unix / Linuxでは、二重匕甚笊の堎合は蚘号「$」で゚スケヌプする必芁がありたす
 perl -e "\$i = 0;print \$i" 

ご泚意 -eフラグの埌、コヌドはすぐに続きたす 。

フラグ-l
このフラグは、倉数$ /および$ \を倀 "\ n"で初期化したす。
$ /倉数は、入力フィヌルドの区切り文字を蚭定したす。
$ \倉数は、印刷コマンドの埌に䜕が印刷されるかを指定したす。

プログラム
 perl -le "print 1" 

以䞋ず同等
 BEGIN { $/ = "\n"; $\ = "\n"; } print 1; 

したがっお、最埌にprint "\ n"ず曞く必芁はありたせん。

フラグ-n
ここから楜しみが始たりたす。

次のコヌド
 perl -ne 'print 1' 

これず同等
 LINE: while (defined($_ = <ARGV>)) { print 1; } 

これはどこで䜿甚できたすか
そしおここでは、たずえば、名前が数字で始たるファむルの名前に拡匵子「bak」を远加する必芁がありたす。

出来䞊がり
 ls | perl -lne 'rename $_, "$_.bak" if /^\d+/' 

そしお、Windows甚 お願い
 dir /b | perl -lne "rename $_, \"$_.bak\" if /^\d+/" 

結果のプログラムを芋おみたしょう
 BEGIN { $/ = "\n"; $\ = "\n"; } LINE: while (defined($_ = <ARGV>)) { chomp $_; rename $_, "$_.bak" if /^\d+/; } 

ムシャムシャ食べる$ _; -lフラグから取埗 -nずずもに、BEGIN {$ / = "\ n";だけでなく、chomp $ _;も远加したす。 $ \ = "\ n"; }

フラグ-a
-aフラグを䜿甚するず、Perlをawkずしお䜿甚できたす。

次のコヌド
 perl -nae "print 1" 

ず同等
 LINE: while (defined($_ = <ARGV>)) { our(@F) = split(" ", $_, 0); print 1; } 

぀たり、各行はスペヌスに分割されお分割され、結果のフィヌルドは@F配列に入れられたす。
フィヌルド区切り文字は、 -Fフラグを䜿甚しお倉曎できたす。

/ etc / passwdファむルからホヌムディレクトリを含むナヌザヌ名を出力するずしたす。
 less /etc/passwd | perl -F: -nlae 'print "$F[0]:$F[4]"' 

たた、たずえばWindowsの堎合、2009幎9月に最埌に倉曎したフォルダヌ内のファむルの名前を調べたいず思いたす。
 dir /TW | perl -nale "print $F[$#F] if $F[0] =~ /\.09\.2009/" 

-Pフラグ
たた、このフラグは-nが「print $ _」で別のcontinueブロックを远加するだけです。

次のコヌド
 perl -pe "print 1" 

ず同等
 LINE: while (defined($_ = <ARGV>)) { print 1; } continue { print $_; } 

ファむル/ etc / passwdを出力し、同時に3を6に眮き換えたずしたす。

このコヌドの代わりに
 less /etc/passwd | perl -ne "s/3/6/;print \$_" 

私たちは曞くこずができたす
 less /etc/passwd | perl -pe "s/3/6/" 

フラグ-i
iフラグを䜿甚するず、ファむルを倉曎できたす。

次のプログラム
 perl -i.bak -pe "s/foo/bar/" 

これず同等
 BEGIN { $^I = ".bak"; } LINE: while (defined($_ = <ARGV>)) { s/foo/bar/; } continue { print $_; } 

これはこれず同等です
 $extension = '.bak'; LINE: while (<>) { if ($ARGV ne $oldargv) { if ($extension !~ /\*/) { $backup = $ARGV . $extension; } else { ($backup = $extension) =~ s/\*/$ARGV/g; } rename($ARGV, $backup); open(ARGVOUT, ">$ARGV"); select(ARGVOUT); $oldargv = $ARGV; } s/foo/bar/; } continue { print; # this prints to original filename } select(STDOUT); 

perl -i.bak -pe“ code” <file name>ずいう行が呌び出されたずきに䜕が起こるかを簡単に説明したす。 たずえば、次のように呌び出したす。
 perl -i.bak -pe "s/foo/bar/" test.txt 

test.txtファむルの名前がtest.txt.bakファむルに倉曎され、新しいtest.txtファむルが䜜成されたす。 次に、゜ヌスファむルの各行で、fooがbarに眮き換えられ、新しいtest.txtファむルに曞き蟌たれたす明らかに、ファむルの名前が倉曎された堎合でも、その行にアクセスできたすか

ファむル内の\ r \ nを\ nに眮き換えたいずしたす
 perl -i.bak -pe 's/\r\n/\n/' test.txt 

このコヌドの結果、2぀のファむルが取埗されたす。1぀は゜ヌスのコピヌであるtest.txt.bak、もう1぀は\ r \ nが\ nに眮き換えられたtest.txtです。

ご泚意 䞊蚘のプログラムを詳现に芋るず$ extension = '.bak'; ...、perl -ibak_ * ...のように呌び出すず、バックアップファむルが「bak_test.txt」ず呌ばれるこずがわかりたす。パラメヌタiの倀にアスタリスクが含たれおいる堎合、この倀は拡匵子ではなくテンプレヌトず芋なされたす。アスタリスクはファむル名を瀺したす。

フラグ-M

-Mフラグを䜿甚するず、モゞュヌルを接続できたす

たずえば、私はCGIモゞュヌルがどこにあるかを知りたい

Windowsの堎合
 perl -MCGI -le "print $INC{'CGI.pm'}" 

Linuxの堎合
 perl -MCGI -le "print \$INC{'CGI.pm'}" 

最近、拡匵子「.cgi」を持぀すべおのファむルに察しおchmod a + xを䜜成する必芁がありたした。
しかし、サヌバヌ䞊で䜕らかの理由でchmodの-Rフラグが機胜しなかったため、これが私がしたこずです。
 perl -MFile::Find -e 'finddepth(sub {print $File::Find::name . "\n"}, "."})' | grep -P '\.cgi$' | perl -nle '`chmod a+x $_`' 

このコヌドでは、「perl -MFile :: Find -e 'finddepthsub {print $ File :: Find :: name。„ \ N“}、”。 "}'」 'FileFindモゞュヌルのfinddepth関数を呌び出したした。珟圚のディレクトリを再垰的にバむパスし、完党なファむルパスを衚瀺したした。

次に、グリップを䜿甚しお、「。cgi」で終わるファむルのみを取りたした-Pはパヌル倧麊の正芏衚珟が䜿甚されるこずを意味したす、次のプログラム「perl -nle '' chmod a + x $ _``」で実行暩を䜜りたした芋぀かったファむル。

このコヌドは次のように曞くこずもできたすが
 perl -MFile::Find -e 'finddepth(sub {$n = $File::Find::name;`chmod a+x $n` if $n =~ /\.cgi$/}, ".")' 

$ _に「\ n」のないファむル名が含たれないように、-lフラグを䜿甚する必芁があるこずに泚意しおください。

しかし、プラグむンパッケヌゞからメむンパッケヌゞにいく぀かの倉数たたはルヌチンを接続する必芁がある堎合はどうでしょうか。
次に、曞く必芁がありたす
 perl -MModule=foo,bar -e '...'; 

たたは
 perl '-Mmodule qw(foo bar)' -e '...'; 

BEGINおよびEND


awkず同様に、最初ず最埌に発生する必芁があるアクションにBEGINずENDを䜿甚できたす。
 perl -e 'BEGIN{< >};<>;END{ }'; 

たずえば、レポヌトの最初ず最埌に40個の「=」蚘号で構成される線を描画したす。
 dir /b | perl -pe "sub line {print '=' x 40 . \"\n\"};BEGIN{line();};END{line()}" 

デバッグする


単䞀行のプログラムをデバッグするには、B :: Deparseモゞュヌルを接続する必芁がありたす。

実行する堎合
 perl -MO=Deparse -ne "print 1" 

出力が埗られたす
 LINE: while (defined($_ = <ARGV>)) { print 1; } -e syntax OK 

B :: Deparseモゞュヌルは、「-MO = Deparse」のように接続する必芁がありたすが、「-MB :: Deparse」のように接続する必芁はありたせん。 どうやらこれは、プログラムでメ゜ッドを䜿甚するだけでなく、このモゞュヌルを䜿甚しおプログラムの゜ヌスコヌドを衚瀺するこずを明確に定矩するために行われたようです。

これは、B :: Deparseモゞュヌルが通垞のモゞュヌルずしお䜿甚される方法です。コヌド出力はありたせん。
 perl -MB::Deparse -e "print 1" 

䞊蚘の䟋では、MO = Deparseを䜿甚しおプログラムコヌドを出力したした。

単䞀行プログラムの䟋


ファむルの行数を出力したすUnix wc -lのアナログ
 perl -ne '}{ print $.' abc.txt 

同等のプログラム
 LINE: while (defined($_ = <ARGV>)) { (); } { print $.; } 

ここでは、トリッキヌなトリック「} {」が䜿甚されおいたす。 私たち自身がサむクルを閉じたした。

バむナリ出力
 perl -e "printf '%b', shift" 200 

ファむル内の\ r \ nを\ nで眮き換える
 perl -i.bak -pe 's/\r\n/\n/' file.txt 

ご泚意 䜕らかの理由で、Windowsでは同様のコヌドは機胜したせんそれは氞続的に\ r \ nを远加し、binmode ARGVを行いたした、
binmode $ ARGV、binmode * ARG {FILEHANDLE}、しかし䜕も圹に立たなかったので、さらに戊いたす。 Windowsで\ r \ nを\ nに眮き換える方法を曞いおいただければ幞いです。

IPアドレスを数字からドットに倉換する
 perl -e "print unpack('N', pack('C4', split /\./, shift))" 127.0.0.1 

珟圚のフォルダヌずそのサブフォルダヌ内の.svnフォルダヌを再垰的に削陀する
 perl -MFile::Find -MCwd -e '$path = getcwd;finddepth(sub {print $File::Find::name."\n"}, "$path")' | grep '\.svn$' | perl -ne 'system("rm -rf $_")'; 

Windowsでも同じこず
 perl -MFile::Find -e "finddepth(sub{ print $File::Find::name . \"\n\"; }, '.')" | perl -ne "print if /.svn$/" | perl -pe "s|/|\\|g" | perl -ne "system(\"rd /s /q $_\");" 

16進IPアドレス出力
 perl -e "printf '%02x' x 4, split /\./, shift" 127.0.0.1 

ファむルの先頭に「/ Usr / bin / perl」ずいう行を远加したす
 perl -i.bak -pe "print \"#!/usr/bin/perl\n\" if $. == 1" abc.pl 

Linux / Unixの堎合
 perl -i.bak -pe 'print "#!/usr/bin/perl\n" if $. == 1' abc.pl 

なぜこれが必芁なのですか


玄束したように、なぜこれがすべお必芁なのかを曞きたす。 find、awk、grep、sedがあるず蚀えたすが、なぜ単䞀行のPerlなのでしょうか

たず、Windowsでは、デフォルトでgrepずawkはありたせん。 はい、もちろんgrepを䜿甚しお行を遞択する方が高速ですが、たずえばファむルの名前を倉曎するなど、もう少し行う必芁がある堎合はどうでしょうか。 結局、あるず蚀う、そうです。 それでは、単線真珠を守るために䜕ず蚀いたすか

そしおここに䜕がありたす

たず、Perlでプログラミングする堎合、Perlを非垞によく芚えおいるので、人を芋ずにすぐに単䞀行のプログラムの䜜成を開始できたす。 ただし、最初は少し珍しいかもしれたせんが、参加するず簡単になりたす

第二に、Perlを䜿甚するず䟿利です。 たずえば、Perlの力でawkの類䌌物-aフラグを参照が必芁な堎合たずえば、単䞀行プログラムでpack、unpack、たたはPerl正芏衚珟を䜿甚したい

第䞉に
Perlは匷力な蚀語です。 単䞀行のperlプログラムは、コマンドラむンのみの通垞のPerlプログラムです。 したがっお、単䞀行の真珠プログラムはさたざたなタスクに䜿甚できたす ただし、長い単䞀行のプログラムを䜜成しない方が良いず思いたす。通垞の真珠のスクリプトを䜜成する方が良いでしょう。

おわりに


grep、find、sed、たたはawkを拒吊するこずを匷くお勧めするだけだずは思わないでください。 私は促したせん 私自身もgrepを䜿い続けおいたす。 Perlでプログラミングする人にずっお䟿利な「1行の真珠」ずしお別の䟿利なツヌルに぀いおお話ししたかったのは、1人を読む必芁がないすでにすべおを芚えおいる、2Perlの力が䜿甚されおいるから

ご枅聎ありがずうございたした。 興味がある人はここに送っおください

perldoc.perl.org/perlrun.html-perldoc、すべおのフラグの説明。
sial.org/howto/perl/one-liner-さたざたな䟋

私はあなたに単語を䜿っお真珠の単䞀行プログラムをグヌグルにするこずを勧めたすワンラむナヌ

曎新
Windowsで\ r \ nを\ nに眮き換えるには、次のように曞くだけです。
 perl -i.bak -ple "s/\r|\n//g;binmode ARGVOUT" file.txt 

アントン・シェルビニンを尊重する

曎新
AntonShcherbininのコヌドに远加された「 s / \ r | \ n // g; 」、それ以倖の堎合はLinuxでbinmodeをロヌルしないだけで、このコヌドは普遍的ですWindowsずLinuxの䞡方で動䜜したす。

アップデヌト2012幎8月26日
<source lang = "Perl"> </ source>タグの䞋のコヌド䟋を曞き盎したした

Source: https://habr.com/ru/post/J70610/


All Articles