[info]karino2


南よ! 海の見える方!


Previous Entry Add to Memories Share Next Entry
パイプ Oriented 環境、PowerShell
[info]karino2
PowerShellはawkに似ています。具体的には、パターンが無くてアクションだけがある感じです。BEGIN、ENDはあります。
概念的な話の前に、最初は幾つか具体例を見てみましょう。

まずはcsvの内容の処理を見てみます。同じような事を書いているPowerShell blogのAWK equivalent in Windows Powershellから例を拝借しましょう。

test.csv

1,Tony Passaquale,7920,20090222 21:59:00,800,4.78,3824,Follow-up
2,Nigel Shan Shanford,30316,20090405 16:34:00,400,9.99,3996,New-Opportunity
3,Selma Cooper,97455,20090405 16:31:00,1000,9.99,9990,Pre-Approach
4,Allen James,95140,20090405 16:31:00,1000,9.99,9990,New-Opportunity

このファイルに対して、以下いろいろ処理をしてみます。
最初に、2番目のフィールドだけ出力してみます。
スクリプトはオリジナルのブログとは変えています。

awk
cat test.csv | awk -F, '{print $2}'

PowerShell
cat test.csv | %{ $_.Split(",")[1] }

どちらもTonyなんちゃらとかをだらだらと出力します。%は引数のブロックを受け取りfor-eachする物です。この時点ではあまり気にしなくてOK。

次に三番目のフィールドを合計してみます。

awk
cat test.csv | awk -F, 'BEGIN {total = 0}{ total+=$3 }END {print "Total:" total}'

PowerShell
cat test.csv | %{$total=0}{ $total += $_.Split(",")[2] }{ "Total: " + $total}

以上から、PowerShellとawkの違いが幾つか分かります。

  1. awkで言う所のパターンは無さそう
  2. awkはBEGINとENDを明示するが、PowerShellは最初のブロックがBEGIN、三番目がEND、と順番で決め打ちである
  3. 自動的にsplitしてくれない。なんたる堕落!
  4. printはいらない。式の評価結果が文字列などの値だと勝手にprintされる(代入の時はされない)
  5. catとかあるらしい
  6. 割と行指向
パターンが無いなんてどうするんだ!という事で、4番目のフィールドが20090405の時だけ3番目のフィールドを足す、というコード、awkで言う所の

awk
cat test.csv | awk -F, 'BEGIN {total = 0} $4 ~ /20090405/ { total+=$3 }END {print "Total:" total}'

を書いてみます。前回との違いは赤字の部分です。
パターンはあえて正規表現で。

PowerShell
cat .\test.csv | ?{ $_.Split(",")[3] -match "20090405" } | %{$total=0}{ $total += $_.Split(",")[2]}{$total}

こうなります。「?」というキーワードが出てきています。
?は、ブロックの中が真の物だけ次のパイプラインに渡す、という物です。
だからデバッグの為「$4が20090405のフィールドだけ出力したい」という時には、

awk
cat test.csv | awk -F, '$4 ~ /20090405/ { print $0 }'

PowerShell
cat .\test.csv | ?{ $_.Split(",")[3] -match "20090405" }

となります。これで$4が20090405にマッチする「行全体」が出力出来ます。

ちなみにcatはUnixと異なり、一行を一Stringオブジェクトずつにぶったぎって送る、という挙動をします。

一つ前の例では少しPowerShellの方が繁雑ですが、こういうデバッグを見てみるとこの形式の利点が分かります。
PowerShellではパイプの後ろを削除するだけです。ところがawkではアクションの中身を変えなくてはいけません。

実際に開発をする時にはパイプラインの左から右へ、出力結果を確認しながら行います。
だからデバッグの為とりあえず出力して結果を目視で確認し、そのままパイプで次につなげて処理を書いていくのはバグも少なく簡単に書いていけます。

PowerShellはこの簡単な例に留まらず、複雑なスクリプトもこの「目視で確認していってパイプラインをつなげていく」という方式で開発をしていきます。

長いスクリプトを結果を見ずに不安になりながら終わりまで書かなくてはいけない、という事はありません。
言語自体やその組み込み関数がパイプラインで開発する事を前提に作られた、パイプ Oriented Languageなのです。
だから自然と細かい単位でコードは分割され、結果は目視で確認する事になります。
PowerShellは、細かい処理をパイプで組み合わせていくというスタイルが、対話的なシェル作業ではもっとも開発生産性が高い、という認識で作られています。

awkはパイプの外の世界と中の世界が分かれている為、awkの中が複雑になりすぎるとperlで書いているような形になってしまいます。
ところがPowerShellはパイプがawkの「中」にとりこまれているので、複雑になってもperlになっていきません。
パイプが多段になっていくだけです。
だからいつまでもUnixでパイプを組み合わせて処理をしている感覚が続きます。
これは後で、制御構造を考えてみる時により明らかとなります。

現在地上に存在する中で、もっともパイプだけを組み合わせて多くのロジックが記述出来る環境、それがPowerShellです。

You are viewing [info]karino2's journal