I ♥ WordPress

[時間割:Perl]『ミニマルPerl』その20
2009/03/03 02:19 posted by kunkichi

どひゃー。ちょっと忙しくてばたばたしている間にもう3月ですよ、トホホ、、、
そろそろ復活しないと〜、ということで月曜日は「Perl」。前回に引き続き、組み込み関数のところ。

今日はリスト処理に絡む関数を。

ミニマルPerl Unix/LinuxユーザのためのPerl習得法
Tim Maher
オライリージャパン
売り上げランキング: 96883
  • sort
    • リストの要素をソートする。デフォルトはアルファベット順。$ perl -wl -e '$,=" "; @ary=("c","a","d","b"); print sort @ary;'
      abcd
    • sortの後にコードブロックで明示的に並べ替え規則を書くとその規則に従ったソートが行われる。ちなみにデフォルトの場合は、本来は以下のコードブロックになっている。$ perl -wl -e '$,=" "; @ary=("c","a","d","b"); print sort { $a cmp $b } @ary;'
      a b c d
    • 数値の場合のコードブロックは以下。$ perl -wl -e '$,=" "; @ary=(14,100,20,8); print sort { $a <=> $b } @ary;'
      8 14 20 100
    • ちなみにこれを文字列としてコードブロックを書くとこうなる。$ perl -wl -e '$,=" "; @ary=(14,100,20,8); print sort { $a cmp $b } @ary;'
      100 14 20 8
    • コードブロックの動作は以下。
      • ソートする項目を$a、$bとする
      • $a と $b を比較演算子で評価する。左辺が大きい場合は-1、イコールは0、右辺が大きい場合は+1を返す。
      • 上記をもとに $a と $b を入れ替える。
    • randを使った無作為ソートの例。randのロジックをコードブロックに記述する。$ perl -wl -e '$,=" "; print sort { int((rand 2)+0.5) -1 } 1..10;'
      2 1 5 9 6 7 4 10 8 3
      randで-1、0、+1のどれかを返すようにすれば、リストのソート規則がランダムになることを利用している。上の例でもあるけれど、文字列・数値それぞれの場合の並べ替え規則はきちんと定義しないとダメだし、かつ、こういう風に定義すればいろいろできるということ。
    • \Lとかを使って、並べ替え規則時に大文字か小文字に統一してやれば、大文字・小文字の違いを無視するソートとかもできる。$ perl -wl -e '$,=" "; print sort { $a cmp $b } "a".."Z","A".."Z";'
      A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z
      これがこうなる。$ perl -wl -e '$,=" "; print sort { "\L$a" cmp "\L$b" } "a".."Z","A".."Z";'
      a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z
  • grep
    • UNIXコマンドのgrepとは異なり、標準入力とかファイルからではなく、リストに対して実実行、コードブロックで条件を記載する$ perl -wl -e '@ary=("John","Paul","George","Ringo");print grep {/^J/} @ary;'
      John
  • join
    • リストの要素を単一のスカラに結合する。$ perl -wl -e 'print join "|", "a".."Z";'
      a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z
    • リストに対してマッチングとか置き換えを実施したい場合、個々の要素に対して実施する場合は個別に処理するしかないけど、複数の要素にまたがった状態に対して実施する場合はjoinで結合しちゃうという手が使える。$ perl -wl -e '$str = join "", "apple","monday"; $str =~ /lemon/ and print "Lemon was found!"'
      Lemon was found!
    • -aオプションでフィールド処理した@Fをjoinすると、セパレータの変換的なこともできる。$ cat /etc/passwd | perl -wnlaF":" -e 'print join "|", @F;' | grep -v "^#"
      nobody|*|-2|-2|Unprivileged User|/var/empty|/usr/bin/false
      root|*|0|0|System Administrator|/var/root|/bin/sh
      ・・・
  • map
    • リストを変換するフィルタ。
    • 使い方はgrepと似ているけど、grepはコードブロックの評価に対して各要素を返すのに対して、mapはコードブロックの評価そのもの、つまり変換した結果を返す。$ perl -wl -e '@ary=("John","Paul","George","Ringo"); $,=" "; print map { "\U$_" } @ary;'
      JOHN PAUL GEORGE RINGO
    • ありがちなミス。$ perl -wl -e '$,=" "; print map { s/^(.)/\L$1/g } @ARGV;' 'John' 'Paul' 'George' 'Ringo'
      1 1 1 1
      これはs/〜/〜/gという置換演算子は、置換後の結果を返すsedコマンドとは異なり、置換に成功した数を返す。また、mapのコードブロックで返されるのは、コードブロック内の最後の処理になるため、置換に成功した数として1がかえってきているという訳。これを回避するには、コードブロックの処理の最後に$_をつけてやる。$ perl -wl -e '$,=" "; print map { s/^(.)/\L$1/g; $_ } @ARGV;' 'John' 'Paul' 'George' 'Ringo'
      john paul george ringo

こういうリスト関連処理って、読み込んだファイルの内容をいったんリストに放り込んどいて、まとめてフィルタ、みたいな感じで使えばかなり便利な気がします。

今日はここまで。

コメント&トラックバック

トラックバックURL

[…] [時間割:Perl]『ミニマルPerl』その20 | cafe chantant blog […]

2009/9/23 水曜日13:30:56 posted by ミニマルPerl Unix/LinuxユーザのためのPerl習得法 | ってどうよブログ





このページの先頭へ