第12回本当は怖くないシェル芸勉強会に参加してきた
2014年08月04日 01時15分
第12回本当は怖くないシェル芸勉強会&第29回本が出たよUSP友の会定例会に参加してきました。
http://usptomo.doorkeeper.jp/events/12763
シェル芸本を買ったは良いけど時間とれずにろくに読めて無く、awkを使ったことがほぼ無い状態でしたがサイン欲しかったというミーハーな理由のみで参戦してみました。
電子書籍の売上は芳しいけど紙の初版を売り切らないと今後のシェル芸本にも悪い影響が出そうなニュアンスをイントロで言っていたので買ってない人は紙媒体もよろしくお願いします。
私は本の冒頭のやり取りだけで十分新しい知見を得られました。
イントロが終わったら急に問題を紹介されて「さ、やってみて」と言われて「えっ、もうやるんすか!?」状態だったけどなんていうかアルゴリズム考えるこの感じ、すっごい久しぶりで学生の時のゲーム作ってる時のような感覚を久々に味わえました。
普段はアルゴリズムというよりはフレームワークに乗っかってひたすら手続き書いてるようなことが多いので頭使う部分がやっぱ全然違うんだということを再認識。
やっぱ何か解決することを考えるのに道が色々あってそれを導きだすのは楽しいです。
ただね、この勉強会は色々なコマンド知ってないと歯が立たないです。
普段からパイプでコマンド3つ以上繋げて無意識にシェル芸している人じゃないと問題に立ち向かえない気がする。
そこでPHPerな私はPHPワンライナーで立ち向かったのです!
というかPHPのワンライナー機能があることをこの会場で調べて初めて知りました。
1 2 3 4 |
cat filename | php -B '{最初に一回行う処理}' -R '{各行に行う処理}' -E '{最後に一回行う処理}' |
PHPにもBEGINとENDがあるんですよ。
-Rには $argnという変数に各行の内容が入り$argiに行番号が入ります。
これで戦える。
問題と正解例を上田さんのブログで公開されています。
http://blog.ueda.asia/?p=3535
で、ノリで下のTweetしたらまさかのピックアップですよ。
awk分からん。もうPHPerであることを隠さない。 cat num | php -R 'echo $argn." ";for($i=0;$i<$argn;$i++){echo "x";}echo PHP_EOL;' #シェル芸
— こん (@konkon1234) 2014, 8月 2
そんでもって上田さんのPCで実行したらphpがインストールされてないからphp-cliをapt-getしろと出てるのを見てphpの場違いさを肌に感じた次第です。
いるのか分からないけど折角だからPHPワンライナーの例です。(可読性の為に改行してますがコマンドは一行です)
Q1
次のように、画面にバッテンを描いてください。(この出力例の大きさは21×21です。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
seq 21 | php -R 'for($i=1;$i<=21;$i++){if($i==$argi||22-$i==$argi){echo "x";}else{echo " ";}}echo PHP_EOL;' #x x # x x # x x # x x # x x # x x # x x # x x # x x # x x # x # x x # x x # x x # x x # x x # x x # x x # x x # x x #x x |
Q2-1
次のechoの出力から回文を完成させてください。
1 2 3 4 |
echo たけやぶ | php -R 'preg_match_all("/./us",$argn,$str); $rstr=array_reverse($str[0]);array_shift($rstr); echo mb_substr($argn,0).implode($rstr);' #たけやぶやけた |
Q2-2
次のファイルの各行について回文を完成させてください。
1 2 3 |
cat kaibun | php -R 'preg_match_all("/./us",$argn,$str);$rstr=array_reverse($str[0]);array_shift($rstr);echo mb_substr($argn,0).implode($rstr).PHP_EOL;' #たけやぶやけた #わたしまけましたわ |
Q3
ウェブ等からデータを取得して南武線の駅名のリストを作ってください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
php -r '$res = json_decode(file_get_contents("http://express.heartrails.com/api/json?method=getStations&line=".urlencode("JR南武線"))); foreach($res->response->station as $station){echo $station->name.PHP_EOL;}' #川崎 #尻手 #矢向 #鹿島田 #平間 #向河原 #武蔵小杉 #武蔵中原 #武蔵新城 #武蔵溝ノ口 #津田山 #久地 #宿河原 #登戸 #中野島 #稲田堤 #矢野口 #稲城長沼 #南多摩 #府中本町 #分倍河原 #西府 #谷保 #矢川 #西国立 #立川 |
Q4
北から順(正確には都道府県番号順)に並べてください。
1 2 3 4 5 6 7 |
cat pref | php -B '$pref=array();' -R '$pref[]=$argn;' -E '$webpage=mb_convert_encoding(file_get_contents("http://elze.tanosii.net/d/kenmei.htm"),'utf8','cp932'); preg_match_all("/(".implode("|",$pref).")/u",$webpage,$matches); foreach($matches[0] as $match){echo $match.PHP_EOL;}' #青森県 #群馬県 #大阪府 #鹿児島県 |
Q5
各行の数字を大きい順にソートしてください。
1 2 3 4 |
cat input | php -R '$arr=explode(" ", $argn);$t=array_shift($arr);rsort($arr); echo $t." ".implode(" ",$arr).PHP_EOL;' #A 1234 31 4 -42 #B 94 31.1 10 -34 |
Q6
次のファイルについてグラフを作ってください。
1 2 3 4 5 6 |
cat num | php -R 'echo $argn." ";for($i=0;$i<$argn;$i++){echo "x";}echo PHP_EOL;' #5 xxxxx #3 xxx #4 xxxx #10 xxxxxxxxxx #2 xx |
Q7
Q6のグラフを次のように縦にしてください。
(多少ズレてもよしとします。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
cat num | php -B 'if(!isset($max)){$max=0;}$nums=array();' -R 'if($max<$argn){$max=$argn;}$nums[]=$argn;' -E 'for($j=0;$j<$max;$j++){for($i=0;$i<count($nums);$i++) {echo ($j<$max-$nums[$i])?" ":" x";}echo PHP_EOL;} foreach($nums as $num){printf("%3s",$num);}echo PHP_EOL;' # x # x # x # x # x # x x # x x x # x x x x # x x x x x # x x x x x # 5 3 4 10 2 |
Q8
次のデータは、何かの試合の結果ですが、各チームが何勝何敗だったかを集計してください。引き分けは無いと仮定して構いません。
1 2 3 4 5 6 7 8 |
cat result | php -B '$result=array();' -R 'list($t1,$t2,$p1,$p2)=preg_split("/( |-)/u", $argn); if($p1>$p2){$w=$t1;$l=$t2;}else{$w=$t2;$l=$t1;}$result[$w]["won"]+=1;$result[$l]["lost"]+=1;' -E '$teams=array_keys($result);sort($teams); foreach($teams as $team){echo sprintf("%s %d勝%d負",$team,$result[$team]["won"],$result[$team]["lost"]).PHP_EOL;}' # A 0勝3負 # B 3勝1負 # C 2勝1負 |
もうね、シェル芸じゃなくPHPですorz
使ってるコマンドなんてseqとcatぐらいしかない気がする。
公式の正解例で使われているコマンド見て勉強します。
でも上田さんが気にしていた「せっかく参加されたんだから新しい知見を見つけて帰って欲しい」というのはちゃんと得れました。
PHPワンライナー。
まぁ会場でコマンドとawkだけでの解決方法がさっぱり分からず、試してみてもエラー出まくりであまりにイライラして得意な土俵に退却しただけなんですけど新しい発見でした。
次はコマンドやawkだけで戦えるように頑張ります。
サインはしっかりしていただきました!
上田さんは想像以上にイケメンなナイスガイでした。