ご挨拶
お久しぶりです。カードファイター石田です。最近、システム部を中心にTCGが地味に流行っております。MTGとヴァンガードをやっています。MTGも好きですが、どちらかと言うと運の要素が強く運を考慮しながらプレイングとデッキを組み立てるヴァンガードの方にちょっと寄り勝ちな昨今です。主デッキは自在感を意識した構築のペイルムーンです。アライドアーキテクツのTCG部ではMTGとヴァンガードの対戦相手を随時募集しております。
今回のテーマについて
ここのところ説教臭い話が多かったので今回は少しタメになる話でもということで、この題材にしました。社内からもチラホラと要望が有ったこともありますし、それなりにニーズも有るのかなと。例えば、ファイル名のある程度ルールのある置換を一括で行う時など、日頃の業務の中の「めんどくせぇ……」から、あなたを解放する一助になれば幸いであります。
対象読者
以下の条件を満たす方が対象です
-
1. シェルを毛嫌いしない人
-
2. プログラムの「変数、ループ、分岐」について理解がある人
-
3. パイプってなに? 位は分かる人
-
4. 怠惰、短気、傲慢を美徳とする人
そもそもPerlって?
ラリー・ウォールの開発した現在地球上に存在するスクリプト言語の中で最強中の最強のスクリプト言語です。ちょっとしたコマンド補助やワンライナー、遺伝子解析、Webアプリ、果てはWindowベースのGUIまで、この世のありとあらゆるところで使われています。この地球はPerlで出来ていると言っても過言ではあります。そうです過言です。今回は豊富なPerlの機能の中でも、”-e” オプションの使い方について説明していこうと思います。
ワンライナーって?
一行野郎です。一行で色んなことをするソースコードを単純にワンライナーと言いますが、ここでは特別に断りの無い限り “-e” オプションを使ってシェル上で実行するワンライナーのことを指します。
準備
Windows以外の人は特に何もせずとも使えると思います。コマンドラインで perl -v って打てば、こんなのが出ると思います。
Windowsの人はCygwinみたいなのを入れるか、ActivePerlやStrawberryPerlを入れるかWindowsは端末だと割り切ってサーバーに繋いでみたりしてPerlを使えるようにしてください。個人的にはCygwinが良いかなと思います。
ステップ1 – とりあえず動かす
文法がどうのとか言う前にとりあえず動かして、どんなものかを試してみるのが良いと思います。コマンドについてはUNIX、Linuxベースで書いていきます。Windowsの人は適宜コマンドを読み替えてください。
-
1. どうでも良いディレクトリに移動します
-
2. mkdir oneliner
-
3. cd oneliner
-
4. touch file1.txt
-
5. touch file2.txt
-
6. touch file3.exe
-
7. touch file4.bat
-
8. ls | perl -anle ‘print $F[0] =~/exe$/ ? “\(^o^)/” : $F[0]’
とりあえず実行してみてください。
ステップ2 – コマンドライン引数の解説
1から7までは特に説明の必要は無いですかね。テストデータにするためのディレクトリとファイルを作っているだけです。では、8についてです。ls の結果をパイプで渡しています。ここまでは普通のシェルですね。ここで普通のシェルではない……とか、理解を超えている…… という場合は普通に”パイプ”でググってください。とりあえずPerlに渡しているコマンドライン引数について説明します。perl -h とかで普通にusageが出るので、そっちを読め!って感じなんですが、そうやって全部丸投げすると説明するコンテンツが無くなってしまって記事にならなくなってしまうので、ここは世界のディスクスペースの無駄なんじゃないかという気持ちをグッとこらえて書くことにします。
nについて(説明の都合のために、aより先にnを説明します)
1 |
assume "while (<>) { ... }" loop around program "usageより" |
ということです。標準入力を一行ずつワンライナーに渡してくれるオプションです。大体、aと一緒に使います。
aについて
1 |
autosplit mode with -n or -p (splits $_ into @F) "usageより" |
ということです。ワンライナー中に出てくる$F[0]ってヤツですね。パイプで渡された行を空白でsplitして$Fの配列に自動で詰め込んでからワンライナーへ渡してくれるというオプションです。
l について
1 |
enable line ending processing, specifies line terminator "usageより" |
要は、print した時、自動で改行を入れてくれるオプションです。ワンライナーしている時には便利です。
eについて
1 |
program one line of program (several -e's allowed, omit program file) "usageより" |
perl に 渡された文字列を、その場で実行します。
まあ、全部覚えなくて良いです。ワンライナーする時には”anle”とか覚えていれば充分です。「ぱーる はいふん あな……」みたいな感じで何度か口に出してみてオプション部分に差し掛かった時に公共の場で発音するのを憚られる気持ちになって口ごもったりしていれば覚えられると思います。
ステップ3 – 実際のコードの説明
$F[0] には、つまりファイル名とかが入ってきます。$F[0] =~ /exe$/ は、正規表現のマッチですね。$F[0] が exe$(exeで終わる文字列)ならば真 という条件文です。真ならば”\(^o^)/”、偽ならば、ファイル名そのままを返すというコードです。
ステップ4 – 応用
ここまででシェルから実行するワンライナーが、どう動くのか、どうやって動かすのか?の一つの側面については大体理解出来たのではないかと思います。ここでPerlの文法の理解を深め、もっと別のコマンドライン引数のパターンを掘っていき、簡単な書き捨てスクリプトを作れるようなところまで持っていくのも良いかなとは思うのですが、まあ、Too muchかなということで。今回は「ぱーる はいふん あ……る」という公の場で発音するのが躊躇われるオプションを利用したワンライナーの応用パターンを列挙して、ちょっと書き換えれば「色んな面倒くせぇを肩代りしてもらえる」というところまでで結ぼうと思います。
Git で ひとつ前のリビジョンのコミットのハッシュ値を出力する
1 |
git log | perl -anle '$F[0] eq "commit" and print $F[1]' | head -2 | tail -1 |
簡単に説明しますと、git log って、以下みたいなのがズラーって出てくるじゃないですか?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
commit hogehogheoghohgoe Author: t_ishida <ishida@aainc.co.jp> Date: Tue Jun 18 18:54:25 2013 +0900 comment,comment,comment commit fugafugafugafuga Author: t_ishida <ishida@aainc.co.jp> Date: Tue Jun 18 18:54:24 2013 +0900 comment,comment,comment commit piyopiyopiyopiyo Author: t_ishida <ishida@aainc.co.jp> Date: Tue Jun 18 18:54:23 2013 +0900 comment,comment,comment |
$F[0] が commit という文字列だった時に $F[1] を出力するので、ワンライナーの結果は以下のようになります
1 2 3 |
hogehogheoghohgoe fugafugafugafuga piyopiyopiyopiyo |
head -2 で 以下の内容になって
1 2 |
hogehogheoghohgoe fugafugafugafuga |
tail -1 で 以下になります。
1 |
fugafugafugafuga |
ファイルサイズが “4” より大きいファイル名を出力する
1 |
ls -al | perl -anle '$F[0] =~/^-/ and $F[4] > 4 and print $F[8]' |
簡単に解説すると、これは、はじめに用意したテストデータにecho ‘hoge’ >> file3.exe ってやった後のものです。そこで、ls -al した結果は、こんな文字列が出力されますね。
カラムの内容を見ていくと、
-
$F[0]の一文字目が “-” のものがファイルです。
-
$F[4]がファイルサイズです。
-
$F[8]がファイル名です。
$F[0] が “-“から始まり、$F[4]が 4より大きければ、$F[8]をprintするということですね。
ファイル名を大文字にしちゃう
1 |
ls | perl -anle '$from = $to = $F[0] and $to =~ tr/a-z/A-Z/ and system "mv $from $to"' |
こういうことですね。あまり解説は要らないと思いますが、補足を。Perlを使わない方にとって、よく分からないところtrじゃないかと思います。対象の変数に格納されている文字列をルールに則って変換するというものです。tr/a-z/A-Z/ は小文字から大文字へ、tr/A-Z/a-z/は大文字から小文字へ。このtrと、$x =~ s/target/replace/ 辺りを調べて堀下げると、もっと応用が効くようになると思います。さらに、-MでCPANモジュールを使うようになってくれば更に可能性が広がります。しょーもないことはPerlに任せて、あなたとあなたの家族の時間を大事にしてください。
締め
アライドアーキテクツでは、カードファイト部と一緒にカードファイトしてくれるカードファイターと2センテンス以上有るプログラムについて「改行が入っていないからワンライナーである」と言い張るヤツを許せないエンジニアを募集しております。
なるべく他のメンバーは書かないであろう流行りとは程遠いところや、 枯れたキーワードについて書いていこうと思います。 Perl / Java / PHP 及び周辺技術に興味があります。