世間はゴールデンウィークですがいかがお過ごしだろうか?そんなの関係なくやること満載な上に、第22シェル芸勉強会の福岡サテライト会場を開催して更にフラフラになっているが、一体どういうことなのだろうか??
ということで、参加者の皆様お疲れ様である。午前の部は、福岡サテライトでは独自の初心者向け内容をやった。午後は今回も期待に違わず、参加者全員の脳天からオーバーヒート煙がモワモワと上がりまくりであった。参加者は途中帰宅した方などを含めると8人だった。イベントページはこちら。
本家イベントページはこちら。
大阪サテライトについてはこちら。
5f01b3bc1d81c1fae2378cdc89.doorkeeper.jp
Twitter投稿まとめはこちら。
イントロ
シェル芸はコンピュータに頑張ってもらうためのスキルなんじゃない?ってことで。
午前の部
福岡サテライトでは比較的初心者の方が多い?と感じていたため、午前の部は私が準備した入門編的な内容について話をしてみた。内容は「シェルで繰り返し処理」について。制御構造やxargs、コマンド列作成してシェルへブチ込む、フィルタコマンド、という流れで話を進めてみた。お題があまり良くなかったかもしれない。
東京本家であっていた午前の部は、資料があれば後で見てみたい。昼は皆さんで外に食事に出かけた。久しぶりに一風堂でラーメンを食らう。
午後の部
さて午後は初心者も手練れも死んでよし!な時間だ。今回もなかなか歯ごたえがある内容で、上田会長いつも問題作成お疲れ様です。しかし毎回こんな問題を考えつく上田会長、一体何者なの??ヤバイの???宇宙人なの????
今回の問題はこちら。
【問題のみ】第22回ゴールデンウィークの存在疑惑シェル芸勉強会 – 上田ブログ
問題と解答はこちら。
【問題と解答】第22回ゴールデンウィークの存在疑惑シェル芸勉強会 – 上田ブログ
各問題について、福岡サテライトで私なりに解説した内容や解答例を載せておく。
Q1
中央値を出すのはどうするか?まあ真ん中のデータを持って来ればええのだが。あっさりとは解けなかったので上田会長の解答例を参考にした。awk
を知らない方がいらっしゃったので、まずはデータを並び替えて横にするところまでのやり方を説明した。
$ cat Q1/a | sort | xargs 1 1 2 3 4 6 6 8
残りはawkの$1やNRやNFについて説明しながら、上田会長の解答例を解説した。
Q2
ギ・ギブ・・ナニコレ・・・。カレーライスと醤油ラーメンをそれぞれ別の行にして、awk
でNR==1
とNR==2
の時にゴニョゴニョするとかかなあと思ったが、敗北。
$ echo カレーライス 醤油ラーメン | tr ' ' '\n'
カレーライス
醤油ラーメン
カレーライスを縦に並べて、左に空白を入れるにはどうすればいいのか?という質問が出たので、こんな感じかなと解説した。grep -o
オプションが驚きだったようだ。
$ echo カレーライス | grep -o . | sed 's/^/ /' カ レ ー ラ イ ス
Q3
ようやく太刀打ち出来そうな問題。Tukubaiコマンドを解禁。行番号を右側に付けて、第一フィールドを優先キーにしてsortする。
$ cat Q3 | awk '{print $0,NR}' | sort -k1,1 -k2,2n aaabbb 1 aaabbb 3 aaabbb 4 bababa 2 bababa 5 bbbbba 6
あとはTukubaiのyarrコマンドで簡単。
$ cat Q3 | awk '{print $0,NR}' | sort -k1,1 -k2,2n | yarr num=1 aaabbb 1 3 4 bababa 2 5 bbbbba 6
Tukubaiコマンドを使わなければ、awk
の連想配列で解ける。
$ cat Q3 | awk '{a[$1]=a[$1]" "NR}END{for(v in a)print v,a[v]}' bababa 2 5 aaabbb 1 3 4 bbbbba 6
逆に復元するにはこんな感じ。Tukubaiコマンド利用。
$ cat Q3.ans | tr -s ' ' | tarr num=1 | sort -k2,2n | awk '{print $1}' aaabbb bababa aaabbb aaabbb bababa bbbbba
Q4
なんとか解けた・・・考え方は、実行するコマンド列を作ってシェルにブチ込む方法。まずは素数の列挙。素数の列挙方法も解説した。
$ seq 10 | gfactor | awk 'NF==2{print $2}' 2 3 5 7
列挙した素数からsedの命令コマンドを作成。
$ seq 10 | gfactor | awk 'NF==2{print $2}' | tr '\n' 'p' | sed 's/p/p;/g' | sed "s/.*/\'&\'/" '2p;3p;5p;7p;'
さらに実行するコマンド列を作成
$ seq 10 | gfactor | awk 'NF==2{print $2}' | tr '\n' 'p' | sed 's/p/p;/g' | sed "s/.*/\'&\'/" | sed 's/^/sed -n /' | sed 's/$/ Q4/' sed -n '2p;3p;5p;7p;' Q4
あとはコマンド列をパイプでシェルに食わせる。
$ seq 10 | gfactor | awk 'NF==2{print $2}' | tr '\n' 'p' | sed 's/p/p;/g' | sed "s/.*/\'&\'/" | sed 's/^/sed -n /' | sed 's/$/ Q4/' | sh りんご みかん りんご りんご
更にそこからsort | uniq -c
の定番処理で集計。
$ seq 10 | gfactor | awk 'NF==2{print $2}' | tr '\n' 'p' | sed 's/p/p;/g' | sed "s/.*/\'&\'/" | sed 's/^/sed -n /' | sed 's/$/ Q4/' | sh | sort | uniq -c 1 みかん 3 りんご
Q4まで終わって一旦休憩。既にこの時点でノーミソオーバーヒート。
Q5
さて午後の部後半開始。いきなり難問・・・とりあえず1から12までの組み合わせを出してみるかと考えた。組み合わせ出すにはbashのブレース展開かな?
まずは実行するコマンド列を作成。
$ seq -f '{,%g}' 1 12 | tr -d '\n' | sed 's/^/echo /' echo {,1}{,2}{,3}{,4}{,5}{,6}{,7}{,8}{,9}{,10}{,11}{,12}
そこからパイプでシェルに食わせて組み合わせ出力。
$ seq -f '{,%g}' 1 12 | tr -d '\n' | sed 's/^/echo /' | bash | tr ' ' '\n' | head 12 11 1112 10 1012 .... 1234567891112 12345678910 1234567891012 1234567891011 123456789101112
ただこれだとダメだ。本当は各数値の間に空白で区切りを入れたいのだが・・・ギブアップ。
Q6
何とか解けた。これはsed
の置換コマンドを作成すればいい。
まずはsedの置換コマンド文字列を作成する。
$ cat Q6_2 | sed 's;^;s/;' | sed 's;$;/;' | tr ' ' '/' s/X/駄馬の首/ s/Y/人間/ s/Z/死相/
あとはこの置換コマンド文字列を、GNU sedの-f -
オプションで標準入力から食わせれば良い。
$ cat Q6_2 | sed 's;^;s/;' | sed 's;$;/;' | tr ' ' '/' | gsed -f - Q6_1 出力は省略
Q7
これわ???多分UNIXのお勉強な問題。まあbashをkill -9
したりすればええんじゃ、という話をしたり。上田会長からはexecの話とかも。
Q8
最後はまたちょっと難問というか何というか。要するに関数名を抜き出せばええのん?ということで下記のように抜き出す。
$ cat Q8.cc | grep '^[a-z]' | grep -vE '(using|main)' void aho(void) string nazo(void)
後はこれを挿入すればええのだが、どうしようか?というところでタイムアップ。上田会長の解説を聞くことにした。
今回も難しかった。が3問解けたのでよしとする。皆さんへの解説をどうするかで頭フル回転だった。解けない問題は重要なポイントの解説を重視するスタイルで福岡サテライトは続けてきたが、かなりアドリブ力を鍛えられたかも?
終了後、Personal Tukubaiとかちょっとした話をした。しかしこんな難問奇問にもかかわらず、参加者が少しずつ定着してきた気がする。午前の部の初心者向け内容も大事な気がしてきた。
今回も上田会長、開催スタッフの方々、大阪サテライトの方々、福岡サテライト参加者の方々お疲れ様!