I ♥ WordPress

[時間割:Perl]『ミニマルPerl』その6
2008/10/28 01:49 posted by kunkichi

火曜日は『Perl』の時間です。行をまたがる正規表現のところから。

  • 普通は . でニューライン(¥n)はとれないのだけど、シングルラインモードを使えば¥nもマッチ対象とすることができる。これを使って複数行にまたがるマッチングを行う。$ cat lines.txt
    abcde fghij
    klmno pqrst
    uvwxyz
    $ perl -00 -wnl -e '/\bfghij\b.*\bklmno\b/si and print $&;' lines.txt
    fghij
    klmno
  • ポイントは以下。
    • 入力レコードセパレータを-00とか-0777とか複数行読み込めるものにする。
    • マッチ修飾子にシングルラインモード(s)を有効にして、¥nがマッチするような正規表現を書く。*. とか。
  • いろいろ試してみる。BINDのqueryログから、問い合わせホスト名が2文字のTLDで終わっているものを参照。$ perl -wnl -e '/query: \S+\.[a-z][a-z] /i and print;' query.log27-Oct-2008 23:28:02.221 queries: client XXX.XXX.XXX.XXX#XXXXX 〜 query: atode.cc IN A +
    27-Oct-2008 23:54:14.192 queries: client XXX.XXX.XXX.XXX#XXXXX 〜 query: www.uniqlo.jp IN A +
    27-Oct-2008 23:59:02.339 queries: client XXX.XXX.XXX.XXX#XXXXX 〜 query: www.oreilly.co.jp IN A +
    さらに.jpドメインのものを除外する。$ perl -wnl -e '/query: \S+\.[a-z][a-z] /i and ! /query: \S+\.jp /i and print;' query.log27-Oct-2008 23:28:02.221 queries: client XXX.XXX.XXX.XXX#XXXXX 〜 query: atode.cc IN A +
  • String::Approxを使ってファジーマッチングも可能。# cat fuzzy_match
    ----------
    #!/usr/bin/perl -s -wnl
    use String::Approx 'amatch';
    amatch $pattern, [ "i", "20%" ] and print;
    ----------
    echo "yafoo" | ./fuzzymatch -pattern='yahoo'
    yafoo
  • スクレイピングの例。www.php.netの右上にあるStableのバージョンのうち、5.X系のバージョンを取得する。$ lwp-request -o text www.php.net | perl -wnl -e '/Stable/ and /5\.\d\.\d/ and print $&;'
    5.2.6

以下、grep処理のまとめ

grepコマンド Perlでの書き方
grep ‘〜’ perl -wnl -e ‘/〜/ and print;’
grep -v ‘〜’ perl -wnl -e ‘/〜/ or print;’
grep -i ‘〜’ perl -wnl -e ‘/〜/i and print;’
grep -l ‘〜’ perl -wnl -e ‘/〜/ and print $ARGV and close ARGV;’
fgrep ‘〜’ perl -wnl -e ‘/¥Q〜¥E/ and print;’

シチュエーションによってはgrepのほうが簡単な場合もあるけど、まあそこはケースバイケースで。ちょくちょく使って慣れていこう。。

[時間割:Perl]『ミニマルPerl』その5
2008/10/15 02:05 posted by kunkichi

さて、祝日分のアップをします。まずは『Perl』から。

ミニマルPerl Unix/LinuxユーザのためのPerl習得法
Tim Maher
オライリージャパン
売り上げランキング: 96883
  • 正規表現でこれまでは、デリミタに¥s+、数値に[0-9]とかでベタに指定してたけど、これからは¥bとか¥dとか使おう。
  • fgrepみたいな、メタキャラクタをそのままリテラルで使う場合は、¥Q…¥E。
  • マッチした部分を取り出す場合は、$&を使う。$ echo "12345 123 abced abc" | perl -wnl -e '/\b\d\d\d\d\d\b/ and print $&;'
    12345
  • マッチしない場合(grep -v)は、orを使う。$ echo "12345
    > 123
    > abcde
    > abc" | perl -wnl -e '/\b\d\d\d\d\d\b/ or print;'
    123
    abcde
    abc
  • 合致するファイル名だけを出力する(grep -l)の場合は、$ARGVでファイル名を取得。perl -wnl -e '/\b\d\d\d\d\d\b/ and print $ARGV and close ARGV;' aaa bbb ccc
    aaa
    最後にcloseしているのは、合致する文字列が複数業あった場合にファイル名が2重に出力されるのを防ぐために、合致した時点でcloseして終わるため。
    ちなみに、closeしないとこうなる。$ perl -wnl -e '/\b\d\d\d\d\d\b/ and print $ARGV;' aaa bbb ccc
    aaa
    aaa
  • 大文字小文字を無視する(grep -i)の場合は、マッチ修飾子iを使う。$ echo "aaa
    > AAA
    > bbb
    > BBB" | perl -wnl -e '/aaa/i and print;'
    aaa
    AAA
  • egrep的だったり、パイプを使った段階的フィルタ、みたいなのはperlだと簡単。perl -wnl -e '/aaa/ and
      /bbb/ and
        /ccc/ and
          /ddd/ and
            print;' sample.txt
    パイプで書くとgrep "aaa" sample.txt | grep "bbb" | grep "ccc" | grep "ddd"メモリ消費やポータビリティの点でPerlのほうがらくちん。
  • 行単位じゃなくて、複数行でのマッチングも簡単。まずは段落。以下のようなldifファイルがあるとして、$ cat sample.ldif
    dn: uid=test1,ou=people,dc=example,dc=com
    uid: test1
    objectclass: posixAccount
    objectclass: account
    userPassword:password1
    loginshell: /bin/bash
    uidNumber: 201
    gidNumber: 201
    homeDirectory: /home/test2
    gecos: test1
    description: "Test User 1"
     
    ・・・
     
    dn: uid=test3,ou=people,dc=example,dc=com
    uid: test3
    objectclass: posixAccount
    objectclass: account
    userPassword:password3
    loginshell: /bin/bash
    uidNumber: 203
    gidNumber: 203
    homeDirectory: /home/test3
    gecos: test3
    description: "Test User 3"
    uidがtest2のレコードを抽出。$ perl -00 -wnl -e '/uid: test2/ and print;' sample.ldif
    dn: uid=test2,ou=people,dc=example,dc=com
    uid: test2
    objectclass: posixAccount
    objectclass: account
    userPassword:password2
    loginshell: /bin/bash
    uidNumber: 202
    gidNumber: 202
    homeDirectory: /home/test2
    gecos: test2
    description: "Test User 2"
  • 今度はさっきのレコードがそれぞれ独立したldifファイルだった場合。この場合はファイルモードを使う。$ perl -0777 -wnl -e '/uid: test2/ and print;' test1.ldif test2.ldif test3.ldif結果は上と同じ。

ここまでは今までにも出てきてるので問題ないね。段落モードとか実際に使えそうなシチュエーションを想定してやってみました。

さて、次回は、「行をまたがる正規表現」からです。これは結構必要となるシチュエーションが多いので重要ですね。

[時間割:Perl]『ミニマルPerl』その4
2008/10/06 22:40 posted by kunkichi

風邪も落ち着いたので今週からまたがんばります!月曜日は『Perl』です。次はPerlでいろいろな*grepコマンドの機能を実装しようという話です。

ミニマルPerl Unix/LinuxユーザのためのPerl習得法
Tim Maher
オライリージャパン
売り上げランキング: 96883
  • *grepの代わりにPerlを使うと方言を統一できる。
    • *grepだと特定のメタキャラクタが使えたり使えなかったり(単語境界の¥bとか)
    • *grepごとの正規表現の方言の違いがあったり
  • 制御文字用のエスケープが豊富。
    • *grepだとあったりなかったり
    • タブを表すのに、Ctrl+V+タブとかで実際に打つよりも長い、とか。
    • ¥dとか¥tとかコンパクトに表せる
  • その他の正規表現の方言も考えなくてよい
    • 繰り返し、より便利な後方参照、メタキャラクタ自体のクォート、コメントの挿入、もっと高度なものまで。
  • マッチング機能
    • レコードの単位を段落にしたりファイルにしたり
    • 行をまたいでマッチング
    • バイナリも扱える
    • ディレクトリは自動的に無視
  • 拡張機能
    • マッチした部分を正規表現の外側で参照
    • 出力レコードのセパレータを変更して出力をカスタマイズ
  • マッチ演算子
    • 通常は/〜/で$_に対するマッチング
    • mで始めるとデリミタを変更できる。%をデリミタにすると、m%〜%
    • =~で変数に対するマッチング。もちろんここでもデリミタは変更できる$str =~ /example/$str =~ m|example|
    • 1行だとこんな感じ$ perl -wnl -e '/example/ and print;' /tmp/sample.txt$ cat /tmp/sample.txt | perl -wnl -e '/example/ and print;'
    • -nと-pはディレクトリを無視してくれる。例えば/etc/yum*を参照する場合、$ ls -td /etc/yum*
      drwxr-xr-x 3 root root 4096  7月 20 20:43 /etc/yum
      drwxr-xr-x 2 root root 4096  7月 16 00:46 /etc/yum.repos.d
      -rw-r--r-- 1 root root  346  6月 22 09:35 /etc/yum.conf
      $ perl -wnl -e '/yum/ and print;' /etc/yum*
      cachedir=/var/cache/yum
      logfile=/var/log/yum.log
      # Note: yum-RHN-plugin doesn't honor this.
      # in /etc/yum.repos.d
      ディレクトリは無視してyum.confファイルの中身だけを参照してくれる。
    • シェルだとシングルクォートのネストはできないので、文字列エスケープ(¥047)を使えばOK。Perlでは普通にバックスラッシュでエスケープできるけど、コマンドラインから実行する場合はあくまでもシェルの制約内。

最近は意識して、仕事でもgrepが使えるケースでもPerlで書いてみるようにしてるので大分なれてきたな〜、この調子この調子。

[時間割:Perl]『ミニマルPerl』その3
2008/09/16 23:53 posted by kunkichi

月曜日は「Perl」です。今日はこれまで出てきた起動オプションをプログラムのタイプ別にまとめるところから。そのまま写しちゃうのはアレなので多少いじってみました。

ミニマルPerl Unix/LinuxユーザのためのPerl習得法
Tim Maher
オライリージャパン
売り上げランキング: 204732
一次オプションクラスタ 用途
-wl 出力 -wで警告表示はお決まりな感じ。-lで行末処理。
# perl -wl -e 'print "Hello, World."'
Hello, World.
#
-wnl 入出力 -nで入力処理のフィルタ。
# echo "Hello,World." | ¥
> perl -wnl -e 's/World/Dolly/g;print;'
Hello,Dolly.
#
-wnla フィールド処理(セパレータは空白文字) -aで空白をセパレータとしたフィールド処理を指定。
# echo "1 2 3" | ¥
> perl -wnla -e 'print $F[2];'
3
個々のフィールドは@Fに入る
-wnlaF’セパレータ文字列 フィールド処理(セパレータは任意文字) -aでフィールド処理を指定、そして-Fでセパレータ文字列を指定。awkっぽい。
# echo "1,2,3" | ¥
> perl -wnlaF',' -e 'print $F[2];'
3
レコード定義クラスタ 用途
-00 段落モード 段落ごとに番号をつけてみる。# cat sample.txt
This is paragraph1.
 
This is paragraph2.
 
This is paragraph3.
# perl -wnl -00 -e 'print "$.: $_";' sample.txt
1: This is paragraph1.
2: This is paragraph2.
3: This is paragraph3.
slapcatしたデータとかこれで処理すればよさげ。
-0777 ファイルモード ファイルごとに番号をつけてみる。# cat sample2.txt
This is paragraph4.
 
This is paragraph5.
 
This is paragraph6.
# perl -wnl -0777 -e 'print "$.: $_";' ¥
> sample.txt sample2.txt
1: This is paragraph1.
 
This is paragraph2.
 
This is paragraph3.
 
2: This is paragraph4.
 
This is paragraph5.
 
This is paragraph6.
 
スイッチクラスタ 用途
-s スイッチで引数による変数処理を追加 例えば-flagで変数$flagを有効化してみる# cat sample.pl
#!/usr/bin/perl -wl -s
 
our( $flag );
 
if( $flag ){
  print "フラグが有効化されました。";
}else{
  print "フラグは無効のままです。";
}
実行すると以下。# ./sample.pl
フラグは無効のままです。
# ./sample.pl -flag
フラグが有効化されました。
モジュールクラスタ 用途
-M’モジュール名 モジュールを有効化する。 モジュールがインストールされているかの確認に使える。# Perl -M'Net::SMTP' -e ''
#
何も出力されなければモジュールはインストールされている。エラーが出力されたら印すt−ルされていない。
プログラムクラスタ 用途
-e ‘実行するPerlのコード コマンドラインから実行したいコードを書く。

上書き編集クラスタってのもあるのだけど、これはまだ出てきていないのでスルー。

でこれらをあらかじめエイリアスとして指定しておけばちょっと便利かも。
# cat .bashrc
alias perl_o='    perl -wl           ' # 出力
alias perl_io='   perl -wnl         ' # 入出力フィルタ
alias perl_iop=' perl -wpl         ' # 入出力フィルタでprintを使う
alias perl_f='     perl -wnla       ' # フィールド処理
alias perl_fp='   perl -wpla       ' # フィールド処理でprintを使う
alias Perl_o='    perl -00 -wl     ' # 段落モードで出力
alias Perl_io='   perl -00 -wnl   ' # 段落モードで入出力フィルタ
alias Perl_iop=' perl -00 -wpl   ' # 段落モードで入出力フィルタでprintを使う
alias Perl_f='     perl -00 -wnla ' # 段落モードでフィールド処理
alias Perl_fp='   perl -00 -wpla ' # 段落モードでフィールド処理でprintを使う

でもスクリプトではこうは行かないのである程度は覚えないと行けない、ということで順序。

ワンライナーの場合

# perl [スイッチクラスタ] [レコード定義クラスタ] [一次オプションクラスタ] [プログラムクラスタ]

スクリプトの場合

#!/usr/bin/perl [スイッチクラスタ] [レコード定義クラスタ] [一次オプションクラスタ]
〜以下コード〜

基本は一次オプションクラスタがあって、それにいろいろ追加した上で、コード部分を書くって言う流れになると。

こういうオプションを駆使した使い方はあんまりやったことなかったのだけど、僕の日常の作業だとオプションを指定せずに(-wTぐらいはつけます)ベタなスクリプトを書くよりも、こっちのほうが活躍する機会は多いかも。そのうちちょっと試してみよう。

[時間割:Perl]『ミニマルPerl』その2
2008/09/08 22:50 posted by kunkichi

月曜日は「Perl」です。今日はdieとwarnについて。

ミニマルPerl Unix/LinuxユーザのためのPerl習得法
Tim Maher
オライリージャパン
売り上げランキング: 204732
  • warnでSTDERRへの出力が可能。print STDERR “〜”と同じ。
  • dieはデフォルトで255を返す。
  • dieやwarnの出力内容に”¥n”をつけると、エラー情報(発生した行番号とかスクリプト名とか)が抑止される。
  • and/orを使った論理演算子は、if/then、if/elseを簡潔に書ける。
  • andはorよりも優先される点に注意。必要な場合はカッコをつける。
    ex) A or B and C ⇒ A or ( B and C)
    なので、AとBの結果、Cを実行したい場合は、
    ex) ( A or B ) and C
  • 逆にAの結果、BとCを実施するようなケースをwarnとexitでうまく使う。
    ex) A or warn “〜” and exit 255;
  • PerlでもawkみたいなBEGIN、ENDが使える!
  • BEGINは初期化とかチェックとかで使える。例えば、とあるスイッチが指定されている場合はBEGINブロックの中で特別な処理を含めた初期化を行い、ENDでサマリ的な内容を出力するとか。
  • $,で配列を出力する場合のセパレータというか文字列を指定可能。デフォルトは”"。配列を”"で括るとスペースになる。”"で括った場合のデフォルト値も$”で指定可能。

やっぱりPerlは特殊変数多いなぁ、こんなの使ったことないや。この辺はチートシート作っておくと便利かも。

次は、ここまで出てきた起動オプションをいろいろなプログラムのタイプ向けにパターン化・標準化したオプションクラスタの予定。

[時間割:Perl]『ミニマルPerl』
2008/09/02 00:30 posted by kunkichi

月曜日は『Perl』の時間。元々はPHPで開発とかもやっていたんだけど、運用の仕事ではPerlをメインで使っていて(ちょこっとしたスクリプトとか)、いつのまにやら一番長く使ってたりします。

なので、それなりにはわかってるつもりなんだけど、ここいらでちゃんと基礎的な勉強をしておこうかなと。選んだのはこれ↓

ミニマルPerl Unix/LinuxユーザのためのPerl習得法
Tim Maher
オライリージャパン
売り上げランキング: 151300


テーマ的にはぴったり(笑)。先週・先々週とちゃんとやっていたのだけど、ふとtaintモードについて改めて調べてたら横道それまくってたので、今週は立ち戻ってちゃんとアップ。基本的にはわかってるところはすっ飛ばして気になるところだけまとめ。

  • ワンライナーで便利なPerlの起動オプション
    • 行末処理(改行する)場合は-lオプション。
    • -nオプションでテキストを1行ずつ処理。フィルタみたいな感じで使える。
      perl -wnl -e ‘print;’ aaa.txt
    • -pオプションでテキストを1行ずつ処理して「表示」も。これだとフィルタ処理だけですむ
      perl -wnl -e ” aaa.txt
    • printfは-lの効果を受けない。あと、printfは%を使う場合は解釈されるので注意。
    • -nや-pだとデフォルトの入力レコードのセパレータは行になるけど、-0数字でセパレータの単位を変更。–00で段落モード。-0777でファイルモード
  • 便利な特殊変数
    • $.で行番号
  • スクリプトで実行
    • スクリプトの場合、-nと-pオプションの場合、もしくは<>(空の入力演算子)の場合はファイル名が引数として取られる。
    • ワンライナーの場合、-eはシングルもダブルもOK。入れ子もOK。シェルはシングルの入れ子はダメ。
    • -sオプションの場合は、-変数名=値が自動的に渡される。
    • Perlの真偽はシェルと逆なので注意。数値だと0、文字列だとNULLやゼロは偽、それ以外は真。
    • -sオプションの場合は、-変数名=値が自動的に渡される。-変数名だけだとこれれが真になる。オプションをトグルで指定する場合なんかに便利そう。
    • -sで-変数名を指定する場合は、ourで宣言しておけば、”used only once”のエラーが出ない、つまりオプション指定となる。
    • -sで-変数名=値を指定する場合は、逆にourで宣言せずに、定義がないことを警告として出すほうがよい。

-sオプションはいいなぁ、ちょっとしたスクリプトのオプションとしては使いやすいし。次はdieとwarnのとこからの予定。

僕に一番向いてるプログラミング言語
2007/10/18 00:17 posted by kunkichi

Lightweight Language AHP

今更Pyth(ry

いや、ほんとまじめに勉強しようと思っています。

学ぶべき10の現代実用プログラミング言語
2007/07/24 19:05 posted by kunkichi

CodeZine にこんな記事が載ってました。

あなたが学ぶべき10の現代実用プログラミング言語

本稿では、アプリケーション開発の現場で実用されているプログラミング言語をピックアップし、それらの言語の特徴や、テキストを表示するまでの簡単なサンプルをご紹介します。これからプログラミング言語を勉強しようと考えている学生や新人開発者の方はもちろんですが、すでにプログラミング言語をいくつか覚え、新しい別の言語を学習しようと考えている方にも参考にしていただけると思います。(CodeZine

以前紹介した『終わってるITスキルトップ10』というエントリとはちょうど逆の内容、ということで載ってたのは以下の10個。

  • C
  • C++
  • Java
  • C#
  • Visual Basic
  • JavaScript
  • Perl
  • Ruby
  • PHP
  • Python

特徴なりサンプルなりはあっちを見てもらうとして、サーバ運用SEとして必要そうなもの・必要だったもの・できればよかったなというものを個人的に上からピックアップしてみる。

(more…)

printf/sprintf で 2進数で出力する
2007/07/24 11:33 posted by kunkichi

メモ。printf/sprintf の 型指定で b を使うと 2進数 で出力できる。Perl 5.6以降っぽい。
$ perl -e 'printf("%3d:%08b\n",$_,$_)for(0..255)'
  0:00000000
  1:00000001
・・・
254:11111110
255:11111111

Solaris8 標準の Perl は 5.003だから自分で書かないと無理かな。

参考:
↓まるまる載ってた。
2進10進数変換

dig の出力に色をつける dig-color(perl版)
2007/07/04 02:09 posted by kunkichi

せっかく『あわせて読みたい』の画像をはっつけたので、どんなサイトが「あわせて」読まれてるのかな?ということで、リンクをたどってみたら、こういうのを見つけました。

cl.pocari.org - dig の出力に色をつける dig-color

dig の出力に色をつける dig-color というのを作ってみました.
リソースレコードタイプは A/NS/CNAME/SOA/MX のみにしか対応していませんので,そのほかのタイプが必要であれば追加してください.

こちらはRubyで書かれているようで、Rubyが入ってない環境は結構あるかなと思ったので、Perlで書き換えてみました。

#!/usr/bin/perl -w
 
use strict;
use warnings;
 
my %colors = (
    "section" => "02;01",
    "comment" => "37",
    "normal"  => "00",
    "A"       => "32",
    "NS"      => "34",
    "CNAME"   => "36",
    "SOA"     => "33",
    "MX"      => "31",
);
 
my @return = readpipe( "dig " . join( " ", @ARGV ));
foreach my $line ( @return ){
    my $color = $colors{"normal"};
    if( $line =~ /^;;.+SECTION:$/ ){
        $color = $colors{"section"};
    }elsif( $line =~ /^;/ ){
        $color = $colors{"comment"};
    }elsif( $line =~ /^(.+\s)(SOA|NS|A|MX|CNAME)(\s.+)$/ ){
        $color = $colors{"$2"};
        # レコードタイプのみに色を付ける場合
        #$line = sprintf "%s\e[%sm%s\e[00m%s\n", $1, $colors{"$2"} ,$2, $3;
    }
    printf "\e[%sm%s\e[00m", $color, $line;
}

ま、単にPerlの書き方に変えただけなんだけど。変数とか配列とかの書き方とか、あとpopen使ったことないのでreadpipeに置き換えただけみたいな、本当にその程度。

むしろ、出力に色を付けるのは詳しく知らなかったので、その辺はいじらないでそのまま動かしたら、サラッと動いちゃったので本人がびっくり、みたいな(爆)

結果はこんな感じ。

dig の出力に色をつける dig-color(perl版)

色がつくだけで何気に見やすくなるんですね。オリジナルの作者の方のアイデアに感謝。

このページの先頭へ