シェル芸勉強会福岡サテライトの開催が、昨年の冬以降途絶えていた。時間が取れなかったり、前回は大雨の影響で中止したり。株式会社レスコ様の会議室を貸していただき、久しぶりに開催出来た。いつもながら会議室担当者の方には感謝。今回は述べ8人の参加者が集った。そのうち新規の方が3人。そのうち2人は遠方からいらっしゃった。
久しぶりの開催でちと不安も。
twitter.com#シェル芸 勉強会サテライト久しぶりなので、進行とサポートがスムーズに出来るかな( ̄▽ ̄;)
— ぱぴろんちゃん🎧 (@papiron) 2018年9月1日
勉強会募集サイト
本家東京会場募集
大阪サテライト会場募集
福岡サテライト会場募集
イベント報告関連
(上田会長による)jus共催 第37回シェル芸勉強会リンク集
(上田会長による)Togetterまとめ
午前の部
最初に話したイントロ。
午前中は鳥海さんによる文字コードの話を聴く予定だったが、方針を変えて主に初参加者向けの話をすることにした。勉強会の趣旨や内容、よく使うコマンドやその使い方、調べ方など。catのオプション、sort、uniq、comm、paste、ls、findとxargsの合わせ技、bc、awkなどを一通り説明。
その後以前実施した「初心者向けシェル芸勉強会」で解いた問題をやってみることにした。
シェル芸初心者向け勉強会
シェル芸勉強会過去問第2回(問題と解答)
解いてもらって解説をしたのは下記の問題。
問題2: 計算
以下のファイル中の数字を全部足し算してください。
$ cat Q2/num 1 2 3 4 5 6 7 8 9 10
文字列処理で数式を作ってbcへ突っ込むという解答を解説。awk NF
は最後に改行を入れるためのおまじない。
$ cat Q2/num | tr '\n' ' ' | tr ' ' + | sed 's/.$//' | awk NF | bc 55
昼食
前回に新規開拓した中華料理店へ。今回も美味し。何故か福岡県や福岡市の良さやアレな事が話題になったり。福岡県と福岡市の相性ってアレだよねとか(自粛)。
午後の部
いよいよ問題にトライの時間。今回は難しくもあるがくだらない問題らしく・・・
twitter.com過去最高難易度になるかと思ってたけど、過去最高のくだらなさになった。 #シェル芸
— 上田 隆一 (@ryuichiueda) 2018年8月31日
twitter.com途方もなくくだらない問題とは #シェル芸
— ぱぴろんちゃん🎧 (@papiron) 2018年8月31日
要するに「シェル芸bot映え」するような出力を目指す問題だった。シェル芸botについては、Twitterを使ってる人はフォローして使ってみて欲しい。作者の方が手動でフォロー返しされたら利用可能になるので、しばしお待ちを。
問題と解答例はこちら。(出題者の上田会長ブログ)
【問題と解答】jus共催 第37回シェル芸bot生きてるかどうか分からないけどシェル芸bot向けシェル芸勉強会 | 上田ブログ
今回はいつも以上に福岡サテライトなりのペースで、というより私なりのペースでフォローや解説を重視しながら進行した。
Q1
FizzBuzzの出力をアニメーション化する問題。福岡ではとりあえずFizzBuzzの問題を解くことにした。普通はループで剰余計算の結果でif文書くが、sedで文字列処理を使った解答を。GNU sedの0~3
の様な行指定がポイント。最後のxargs
は縦スペース節約。
$ seq 30 | sed '0~3s/$/Fizz/;0~5s/$/Buzz/;' | sed 's/^[0-9][0-9]*\([^0-9][0-9]*\)/\1/' | xargs 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz
Q2
福岡では下記の出力を出すことまでを目標にした。
/\ / \ / \ / \
上田会長の解答前半部を解説した。GNU sedのラベルを使った繰り返し処理という初心者殺しな内容だったが、とりあえず理解してもらえたようだ。繰り返しのb
コマンドは無限にくり返す。
$ echo ' /\' | sed ':a p;s@ /@/ @;b a' /\ / \ / \ / \ / \ ..(無限君)...
繰り返しコマンドでb
の代わりにt
を使うと、直前のsコマンドが失敗するまで繰り返す。
$ echo ' /\' | sed ':a p;s@ /@/ @;t a' /\ / \ / \ / \ / \
Q3
問題簡略化のため、3桁の数字で各桁を足すと15になる数字の列挙をする事にした。bashのブレース展開、sedで空白を入れる、awkで処理という流れ。
$ echo {0..9}{0..9}{0..9} | tr ' ' '\n' | sed 's/./& /g' | awk '$1+$2+$3==15' | tr -d ' ' | xargs 069 078 087 096 159 168 177 186 195 249 258 267 276 285 294 339 348 357 366 375 384 393 429 438 447 456 465 474 483 492 519 528 537 546 555 564 573 582 591 609 618 627 636 645 654 663 672 681 690 708 717 726 735 744 753 762 771 780 807 816 825 834 843 852 861 870 906 915 924 933 942 951 960
awkの-F ''
オプションで空文字を区切り文字に指定すると、$1
から順に1文字ずつ扱えて便利。
$ echo {0..9}{0..9}{0..9} | tr ' ' '\n' | awk -F '' '$1+$2+$3==15' | xargs 069 078 087 096 159 168 177 186 195 249 258 267 276 285 294 339 348 357 366 375 384 393 429 438 447 456 465 474 483 492 519 528 537 546 555 564 573 582 591 609 618 627 636 645 654 663 672 681 690 708 717 726 735 744 753 762 771 780 807 816 825 834 843 852 861 870 906 915 924 933 942 951 960
Q4
bash4の機能でUnicodeのコードポイントを指定した文字表示が可能という解説。macのログインシェルはbash3なので出来ない。Macの人はhomebrewで別途bash4をインストールしてもらった。
$ echo -e \\U1F000 🀀
空文字の列とブレース展開して、同じ文字を繰り返し表示してみるところまでやってみた。
$ echo -e \\U1F00{0,1,2,3,6}{,,,} 🀀 🀀 🀀 🀀 🀁 🀁 🀁 🀁 🀂 🀂 🀂 🀂 🀃 🀃 🀃 🀃 🀆 🀆 🀆 🀆
Q5
上田会長の解答例について前半部を解説。「山田」という漢字を下記の様にバナー化する出力を考える。
__@__ __@__ __@__ @_@_@ @@@@@ _____ @@@@@ @_@_@ @@@@@ @_@_@ @@@@@
上記のバナーを1行ずつ確認すると、下記の3パターンになる事が分かる。
@@@@@ (5列とも埋まる) __@__ (3列目だけ埋まる) @_@_@ (1列目、3列目、5列目が埋まる) _____ (全て埋まらない)
上記の4パターンを1列に並べて、バナー化した「山田」が出るようにawkで順番に指定して出力する。1行目から3行めは3列目だけ埋まるパターン、4列目は1列目、3列目、5列目が埋まるパターンという具合。
$ echo '@@@@@ __@__ @_@_@ _____' | awk '{print $2,$2,$2,$3,$1,$4,$1,$3,$1,$3,$1}' | xargs -n1 __@__ __@__ __@__ @_@_@ @@@@@ _____ @@@@@ @_@_@ @@@@@ @_@_@ @@@@@
Q6
時間がなかったため飛ばした。
Q7
まずはfiglet
とtoilet
コマンドについて解説。インストール出来る人はインストールしてもらった。次にmecabを使ってカタカナに変換。awkで-F , '{print $NF}'
と指定すると、カンマ区切りで最後の列のみを表示することを利用。
$ echo とじ丼 | mecab -E '' | awk -F , '{print $NF}' トジ ドンブリ
あとは改行を外してtoiletコマンドへ。
$ echo とじ丼 | mecab -E '' | awk -F , '{print $NF}' | tr -d '\n' | toilet m m m m # ""m # # # # # mm m mm#m" #mm mm #mm " # """" # # ""m " m" # ""m # # # m" # m" m" # "mm"" # "mm"" mm" m "m # # # # # # m"
上田会長の解答だと、漢字を平仮名にするのにkakasiを使っていた。こちらの方が簡単だったか。そういえばkakasiを使った事があんまりなかったかも。
Q8
簡略化のため下記の様な出力をする事に。1行を左右逆にして2行目に出す。
鉄皿鶏のチリソース定食 食定スーソリチの鶏皿鉄
まずは左右逆にするrevコマンドを解説。
$ echo 鉄皿鶏のチリソース定食 | rev 食定スーソリチの鶏皿鉄
次にmoreutilsに含まれるpeeコマンドを解説。上記のrevコマンドを利用して下記の通り。
$ echo 鉄皿鶏のチリソース定食 | pee cat rev 鉄皿鶏のチリソース定食 食定スーソリチの鶏皿鉄
peeコマンドの代わりに、teeコマンドとプロセス置換の組み合わせでも可能。
$ echo 鉄皿鶏のチリソース定食 | tee >(cat) >(rev) > /dev/null 鉄皿鶏のチリソース定食 食定スーソリチの鶏皿鉄
終了後
シェル芸勉強家の問題を解く時間が終わった後は、午前に引き続き初心者向けの話と「初心者向けシェル芸勉強会」でやったウォーミングアップ問題を解いてもらった。
色々と話をしたのだが、ここではコマンドライン自体もテキストデータだと思うと面白いよという話題を書く。数字の列挙から、日付を列挙するコマンド列をテキスト処理で作成。
$ seq 0 2 | sed 's/^/date -d "/' | sed 's/$/ day"/' date -d "0 day" date -d "1 day" date -d "2 day"
作成したコマンド列をパイプでbashへ渡して実行。繰り返し処理が無くてもコマンドが順次実行されるよ。
$ seq 0 2 | sed 's/^/date -d "/' | sed 's/$/ day"/' | bash 2018年 9月 4日 火曜日 23:06:42 JST 2018年 9月 5日 水曜日 23:06:42 JST 2018年 9月 6日 木曜日 23:06:42 JST
最後に下記の解いてもらった。
問題: 下記の日付一覧から、月毎の日の数を数えてください
$ cat date1 20150101 20150121 20150201 20150202 20150203 20150310
ポイントは年月までの左から6文字だけを切り出す事。6文字を切り出すにはcut -c1-6
やawk {print substr($0,1,6)}
という意見が出た。他にはgrepを使った下記も補足しておいた。
$ cat data1 | grep -o '^......' 201501 201501 201502 201502 201502 201503
後はuniq -c
を使って集計すれば良い。
$ cat data1 | grep -o '^......' | uniq -c 2 201501 3 201502 1 201503
更にsort -nr
までつなげて多い順に並べるのは、良く使うイデェオムだね。
$ cat data1 | grep -o '^......' | uniq -c | sort -nr 3 201502 2 201501 1 201503
全体を通して
今回は2名の方が遠方からいらっしゃった。プログラミングの勉強をしていて、興味本位で参加してみたという方も。参加者の間口が少しでも広がるのは良い事だと思う。
とりあえず福岡サテライトは私のアドリブでペース配分してみよう。後は参加者の反応をもっと見たり、時間をとる必要もありそうだ。
終了後の後片付けで頼まれていた外の張り紙を外し忘れるミスをやってしまい、会場管理の方にご迷惑をおかけしてしまった。次回からは張り紙外しを忘れないようにせねば。