I ♥ WordPress

[時間割: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;'
    kunkichi
    Perlだと、こんなことしなくても、ケチなマッチング(+の後の?がそれ)を使って「マッチする最短の単位」で拾える。$ perl -wnl -e 's/^(.+?):/$1/g and print $1;' /etc/passwd
    kunkichi
    うーん、awk でできないよ、っていうよい例が出ませんでした、笑
  • レコードセパレータのマッチング。改行とかもマッチングで拾えるということ。サンプルとして以下のようなテキストデータがあるとしてThis is a sample sentence and
    using Perl, you can match new
    line with regular expression.
    “new line”をマッチさせてみる。$ perl -00 -wnl -e '/new\nline/ and print;' sample.txt
    This is a sample sentence and
    using Perl, you can match new
    line with regular expression.
    ちなみに\sでもOK。$ perl -00 -wnl -e '/new\sline/ and print;' sample.txt

特殊変数いろいろ

  • 以下のサンプルデータを使います。# cat beatles.txt
    John Lennon
    Ringo Starr
    Paul McCartney
    George Harrison
    awkの場合、$ awk '{ print NR ":" $0 "(Nickname:" $1 ")"  }' beatles.txt
    1:John Lennon(Nickname:John)
    2:Ringo Starr(Nickname:Ringo)
    3:Paul McCartney(Nickname:Paul)
    4:George Harrison(Nickname:George)
    同じことをPerlでやると、$ 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
    1 2 3 4 5 6 7 8 9 10
    セパレータを入力・出力で切り替えてみます。AWKの場合、awk 'BEGIN{RS=" ";ORS=",";}{ print $0 }' sample.txt
    1,2,3,4,5,6,7,8,9,10
    Perlの場合、perl -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|Lennon
    Ringo|Starr
    Paul|McCartney
    George|Harrison
    Perlで。perl -wnlaF"\s" -e 'BEGIN{$,="\|";}print $F[0],$F[1];' beatles.txt
    John|Lennon
    Ringo|Starr
    Paul|McCartney
    George|Harrison
    Perlの場合は入力フィールドセパレータは変数がないので-Fを使う点に注意。
  • フィールド数
    AWKの場合、$ awk '{ print NF }' beatles.txt
    2
    2
    2
    2
    Perlの場合、$ perl -wnla -e '$num=@F;print $num;' beatles.txt
    2
    2
    2
    2
  • 引数の取得。
    AWKの場合、$ cat argv.awk
    BEGIN{
      print "ARGV=\"" ARGV[0],ARGV[1],ARGV[2] "\"";
      print ARGC;
    }
    $ awk -f argv.awk arg1 arg2
    ARGV="awk arg1 arg2"
    3
    AWKの場合は、自分自身も引数に含まれる。Perlの場合。$cat argv.pl
    !/usr/bin/perl -wl
     
    print "ARGV=\"$ARGV[0] $ARGV[1]\"";
    my $num = @ARGV;
    print "$num";
    $ perl argv.pl arg1 arg2
    ARGV="arg1 arg2"
    2
    Perlの場合は自分自身は引数に含まれない($0を使う)

変数展開

  • 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





このページの先頭へ