[時間割:Perl]『ミニマルPerl』その10
2008/12/17 22:56 posted by kunkichi
どっひゃー!もう12月も半ばまで。サボりにサボりまくったな〜、、、とはいうものの一応本はどんどん読み進めてまして、いろいろと活用もしております、はい、、、さて、気を取り直してアウトプット再開です。
前回(ってかなり前だな、、、orz)sedのところまで進んでたので、今回からはAWKの機能をperlで実現していきます。
AWKよりもPerlが優れているところ
- けちなマッチングが行える。
例えばkunkichi:*:100:100:Test User1:/bin/bash:みたいな/etc/passwdのエントリの1カラム目だけが取りたい場合。普通に書くと、$ perl -wnl -e 's/^(.+):/$1/g and print $1;' /etc/passwdとなってうまく行かないパターンにハマりがち。もちろん以下のように正規表現で”:”を考慮するように見直せばオーケーだけど、、
kunkichi:*:100:100:Test User1:/bin/bash$ perl -wnl -e 's/^([^:]+):.*/$1/g and print $1;'Perlだと、こんなことしなくても、ケチなマッチング(+の後の?がそれ)を使って「マッチする最短の単位」で拾える。
kunkichi$ perl -wnl -e 's/^(.+?):/$1/g and print $1;' /etc/passwdうーん、awk でできないよ、っていうよい例が出ませんでした、笑
kunkichi - レコードセパレータのマッチング。改行とかもマッチングで拾えるということ。サンプルとして以下のようなテキストデータがあるとして
This is a sample sentence and“new line”をマッチさせてみる。
using Perl, you can match new
line with regular expression.$ perl -00 -wnl -e '/new\nline/ and print;' sample.txtちなみに\sでもOK。
This is a sample sentence and
using Perl, you can match new
line with regular expression.$ perl -00 -wnl -e '/new\sline/ and print;' sample.txt
特殊変数いろいろ
- 以下のサンプルデータを使います。
# cat beatles.txtawkの場合、
John Lennon
Ringo Starr
Paul McCartney
George Harrison$ awk '{ print NR ":" $0 "(Nickname:" $1 ")" }' beatles.txt同じことをPerlでやると、
1:John Lennon(Nickname:John)
2:Ringo Starr(Nickname:Ringo)
3:Paul McCartney(Nickname:Paul)
4:George Harrison(Nickname:George)$ perl -wnla -e 'print "$.:$_(Nickname:$F[0])"' beatles.txt
1:John Lennon(Nickname:John)
2:Ringo Starr(Nickname:Ringo)
3:Paul McCartney(Nickname:Paul)
4:George Harrison(Nickname:George) - セパレータ関連
以下のサンプルデータを使います。$ cat 1_10.txtセパレータを入力・出力で切り替えてみます。AWKの場合、
1 2 3 4 5 6 7 8 9 10awk 'BEGIN{RS=" ";ORS=",";}{ print $0 }' sample.txtPerlの場合、
1,2,3,4,5,6,7,8,9,10perl -wnl -e 'BEGIN{$/=" ";$\=","}print;' sample.txt
1,2,3,4,5,6,7,8,9,10 - フィールドセパレータ。さっきのbeatles.txtをサンプルに使います。
AWKの場合、awk 'BEGIN{FS=" ";OFS="|";}{ print $1, $2;}' beatles.txt John|LennonPerlで。
Ringo|Starr
Paul|McCartney
George|Harrisonperl -wnlaF"\s" -e 'BEGIN{$,="\|";}print $F[0],$F[1];' beatles.txtPerlの場合は入力フィールドセパレータは変数がないので-Fを使う点に注意。
John|Lennon
Ringo|Starr
Paul|McCartney
George|Harrison - フィールド数
AWKの場合、$ awk '{ print NF }' beatles.txtPerlの場合、
2
2
2
2$ perl -wnla -e '$num=@F;print $num;' beatles.txt
2
2
2
2 - 引数の取得。
AWKの場合、$ cat argv.awkAWKの場合は、自分自身も引数に含まれる。Perlの場合。
BEGIN{
print "ARGV=\"" ARGV[0],ARGV[1],ARGV[2] "\"";
print ARGC;
}
$ awk -f argv.awk arg1 arg2
ARGV="awk arg1 arg2"
3$cat argv.plPerlの場合は自分自身は引数に含まれない($0を使う)
!/usr/bin/perl -wl
print "ARGV=\"$ARGV[0] $ARGV[1]\"";
my $num = @ARGV;
print "$num";
$ perl argv.pl arg1 arg2
ARGV="arg1 arg2"
2
変数展開
- AWKではダブルクォートの中での変数展開ができないので、ちょっとややこしい。
$ awk 'BEGIN{GUITAR="John";}{ if( $1 ~ "^" GUITAR ) print $0; }' beatles.txt
John Lennon
- Perlだとらくちん
$ perl -wnl -e 'BEGIN{$guitar="John";}/^$guitar/ and print;' beatles.txt
John Lennon
その他
- -i拡張子機能はAWKにはない。
- セパレータで区切られた文字列を自動的にフィールドに入れる機能はPerlではデフォルト無効。AWKでは常に有効。仮に使わなくても。
- Perlはモジュールが使える。
AWKのほうが優れている点
- シンプルなプログラムではサイズが小さくなる。
- 引数の個数がARGCという変数だけでとれる。Perlは@ARGVをスカラーに一旦入れないといけない。
とりあえずAWKとの違いはこんな感じ。まあgrepやsedに比べるとそれほど大きな差はないけど、AWKでできることは大概できるって感じかな。
次回も引き続き、PerlでAWKの処理をやります。AWKの神髄とも言えるフィールド処理の話です。では。





コメント&トラックバック
トラックバックURL:
はいっオッパピー!!こんにちは初めてコメントします。私は今pythonを勉強してるんですけど、よく理解できません。いい勉強法などあったら教えてください。毎日見ようと思うのでちゃんと更新してくださいね♪♪
2008/12/26 金曜日4:30:55 posted by Binchan
すんません、長々とサボっておりましたが、新年を迎え、再開しています。
私も以前はPythonもやっていたのですが、C と Perl だけで手一杯なので、また余裕ができればそのうち再開したいと思っています。
2009/1/5 月曜日22:51:16 posted by kunkichi