もう12月に突入したことが信じられない今日この頃だが、朝の寒さにちょっと負けそうになりながらもシェル芸勉強会の福岡サテライトを開催させていただいた。会場は株式会社レスコ様の会議室。素敵な会場でいつもありがたい。今回は総勢5人の参加者が集った。
勉強会募集サイト
本家東京会場募集
大阪サテライト会場募集
福岡サテライト会場募集
イベント報告関連
今回のTLなどはどうだったのかな?
(上田会長による)jus共催 第32回 シェル芸勉強会の報告
jus共催 第32回全くインスタ映えしないシェル芸勉強会 | 上田ブログ
(上田会長による)Togetterまとめ
午前の部
午前中は鳥海さんによる、変態としか思えない領域にも勇敢に立ち向かう激・Perl講習会。最初から撃沈するオープニングだったが、しばらくするとそれは前座であってまだ始まってすらいないことに気がつく・・・内容的には下記のような処理が序の口の中の序の口という感じで・・・
$ echo 1234567 | perl -pe 's/(?<=\d)(?=(\d{3})+$)/,/g' 1,234,567 $ echo 1234567 | perl -pe 's/(.)(?=(\d{3})+$)/$1,/g' 1,234,567
内容が激しすぎて読むのに「覚悟」が必要な鳥海さんによる資料をご覧あれ。バックトラックの処理が見え見えになる、Perlの正規表現デバッグモードとかの話も。
昼食
いつも行く餃子の王将とは違う中華料理店に行ってみたら、なかなか美味しかった。違う店を探索してみるのもええんじゃないかしら?
午後の部
午後はいよいよシェル芸勉強会の問題。ちなみに今回の問題と解答がどんな感じだったかというと・・・
twitter.comシェル芸勉強会の問題ができましたが、自分で見て「これはひどい」と・・・ #シェル芸
— Ryuichi Ueda (@ryuichiueda) 2017年11月30日
問題と解答例はこちら。(出題者の上田会長ブログ)
【問題と解答】jus共催 第32回全くインスタ映えしないシェル芸勉強会 | 上田ブログ
今回も福岡サテライトなりのペースで、フォローや解説を重視しながら進めていった。
Q1
抜けた数字を空行で飛ばして出力する問題。上田会長の解答例はawkの配列を使ったものだった。
福岡からは1から9までの数字の列と重複比較する解答例を出しておいた。下記のようにuniq -c
で重複数をカウントしておく。
$ echo 14679 | grep -o . | cat - <(seq 1 9) | sort | uniq -c 2 1 1 2 1 3 2 4 1 5 2 6 2 7 1 8 2 9
あとは重複数が1の場合は空行を、2の場合はそのまま出力で完成。
$ echo 14679 | grep -o . | cat - <(seq 1 9) | sort | uniq -c | awk '$1==1{print ""}$1==2{print $2}' 1 4 6 7 9
重複しているかどうか?で考えるということで、この問題はcomm
コマンド案件だなと思ってたら、やっぱり解答例が出ていた。comm
コマンドの解説もしておいた。
twitter.comQ1
— くんすと (@kunst1080) 2017年12月2日
echo 14679 | grep -o . | comm -2 - <(seq 9) #シェル芸
twitter.comecho 14679 | grep -o . | comm - <(seq 9) | cut -f3#シェル芸
— きゃろさん (@Carol_815) 2017年12月2日
Q2
Q1の発展系だが・・・ギブアップ。
ASCIIコード使った解答を考えていたら下記の解答例を発見。
twitter.comecho 14679 | grep -o . | diff -y - <(seq 9) | cut -c1 | awk '!NF{printf sprintf("%c", n++)};4' n=97
— =WEBSERVICE("ぐれさん") (@grethlen) 2017年12月2日
| awk NF#シェル芸#Q2
下記の補足解説をしておいた。
awkのファイル名引数
ファイル名指定の代わりにvar=value
の指定が可能。
$ man gawk コマンドラインで指定されたファイル名が var=val という形式ならば、 それは変数への代入であると解釈されます。 変数 var は値 val に設定されます (これは、すべての BEGINブロックを実行したあとに行われます)。 コマンドライン での変数の代入は、AWK が入力をフィールドやレコードに 分割するためのセパレータを実行時に変更するのに便利です。 また、1つのデータファイルに対し数回処理を行う必要がある場合、 状態をコントロールするのにも便利です。
ASCIIコードの扱い
# asciiコードの確認 $ man ascii # 10進数でasciiコードが97の文字を出力。 $ awk 'BEGIN{printf "%c\n" 97}' a # 16進数でasciiコードが`0x61`の文字を出力 $ echo 61 | xxd -p -r a
Q3
問題の意味を間違えていた・・・素数のポート番号を取り出すと勘違い。まあ会長の解答どおりか。
Q4
rs
コマンドで行列ひっくり返したり、tac
コマンドで上下反転させたり、色々考えたがギブアップ。会長の解答を見てもまだピンと来ず・・・
Q5
多分正規表現の問題だと思ったのだが、あえて文字コードを使った解答を考えた。
Macのod
コマンドを使って文字コードの対応を確認してみる。ウムラウトは16進数c3
で始まる2バイト長の文字のようだ。MacやFreeBSDなどのBSD系OSに付属するod
コマンドは、マルチバイト文字の出力に対応しているので分かりやすい。
# Macのodコマンド $ od -t cx1 umlaut.txt 0000000 w ä ** s c h s t w a s h 山 ** 77 c3 a4 73 63 68 73 74 20 77 61 73 68 20 e5 b1 0000020 ** 田 ** ** x S c h r ö ** d i n g b1 e7 94 b0 78 20 53 63 68 72 c3 b6 64 69 6e 67 (以下省略)
ちなみにLinux付属のGNU製od
コマンドは、下記のようにマルチバイト文字部分が表示出来ない。
# Linux(Ubuntu)のodコマンド $ od -t cx1 umlaut.txt 0000000 w 303 244 s c h s t w a s h 345 261 77 c3 a4 73 63 68 73 74 20 77 61 73 68 20 e5 b1 0000020 261 347 224 260 x S c h r 303 266 d i n g b1 e7 94 b0 78 20 53 63 68 72 c3 b6 64 69 6e 67 (以下省略)
勉強会の時間では解答出来なかったので、後ほど考えた解答がこちら。出来ればループを使わず解きたかったが上手くいかず。実行速度の効率は遅いがとりあえず気にせず。
まずは1単語ずつxxd
コマンドで16進数ダンプをとる。後の処理を考えて各単語の最後に改行0a
を入れておく。
$ cat umlaut.txt | tr ' ' '\n' | xargs -I@ bash -c 'echo @ | xxd -p' 77c3a473636873740a 776173680a e5b1b1e794b0780a (以下省略)
grepでc3
で始まる4文字(ウムラウト)の16進数がある行を選び、xxd
コマンドで元の文字に戻す。改行付きで16進数にしていたので、各単語が改行で区切られて出力している。
$ cat umlaut.txt | tr ' ' '\n' | xargs -I@ bash -c 'echo @ | xxd -p' | grep c3.. | xxd -p -r wäschst Schrödinger Ö Übel Ärztin
Q6
Twitterの画面内にツイート数が表示されているので、スクレイピングしてツイート数の変化を検知すれば良い。スクレイピング自体はcurlを使って下記のようになる。
$ curl --compressed -s https://twitter.com/papiron | grep -o 'title="[,0-9]*ツイート"' | sed 's/title="\(.*\)ツイート"/\1/' | tr -d ',' 18690
自分のTwitterアカウントをcurl
コマンドで5秒毎に監視する解答例がこちら。横着して最初の1回目はエラーが出るが気にしない・・・
$ while true; do n=$(curl --compressed -s https://twitter.com/papiron | grep -o 'title="[,0-9]*ツイート"' | sed 's/title="\(.*\)ツイート"/\1/' | tr -d ','); [ "$n" -ne "$pre" ] && echo んほぉ!; pre=$n; sleep 5; done
Mac付属のcurl
コマンドだと圧縮された状態で出力されるので--compressed
オプションで解凍している。
$ curl -s https://twitter.com/papiron | file - /dev/stdin: zlib compressed data $ curl --compressed -s https://twitter.com/papiron | file - /dev/stdin: HTML document, UTF-8 Unicode text, with very long lines
Q7
sed
コマンドで置換や、tr
コマンドで行列置換や考えたがギブアップ。
ebanさんがImageMagick画像処理を使って解答していた・・・ふえぇ。
twitter.comImageMagickででけた。
— eban (@eban) 2017年12月2日
Q7 $ cat image.txt |sed '1iP1 23 6' | convert - -morphology Convolve '3x3: 0 1 0 1 0 1 0 1 0' -negate -morphology Convolve '3x3: 0 1 0 1 0 1 0 1 0' -negate -compress none PBM: | sed '1,2d;s/ //g'#シェル芸
Ubuntuで実行したら最後に整形が必要だったので、追記してみた。
# Ubuntuで実行。ImageMagickのバージョンは6.8.9-9。 $ cat image.txt |sed '1iP1 23 6' | convert - -morphology Convolve '3x3: 0 1 0 1 0 1 0 1 0' -negate -morphology Convolve '3x3: 0 1 0 1 0 1 0 1 0' -negate -compress none PBM: | sed '1,2d;s/ //g' | tr -d '\n' | fold -w 23 00000000000000001000000 00000000001111111100000 00001100011111111110000 00011110001111111111000 00001100000111111110000 00000000000000001000000
このImageMagickでの解答、Macで実行すると上手くいかず。ImageMagickのバージョンが新しいのが原因か?
# Macで実行。ImageMagickのバージョンは7.0.7-13。 $ cat image.txt |gsed '1iP1 23 6' | convert - -morphology Convolve '3x3: 0 1 0 1 0 1 0 1 0' -negate -morphology Convolve '3x3: 0 1 0 1 0 1 0 1 0' -negate -compress none PBM: | sed '1,2d;s/ //g' 00000000000000000000000 00000000000000010000000 00000000000111111100000 00001100000111111100000 00000000000000010100000 00000000000000000000000 # 出力結果が解答と違う
Q8
ギブアップ・・・Unicodeプロパティを使った正規表現で出来るようだ。
全体を通して
午前の部も午後の部も、難易度は高めだったか?福岡会場の場合はサポート重視でやっていく必要がまだまだ高いのが現状でもあるが、自分としてはアドリブを効かせてポイントを説明したりする訓練の場でもある。
また参加者の方が主体になれるようにするにはどうするか?という点も悩みではある。しかし続けていくことで何か見えてくるかもしれない。
先日はTwitter上で、福岡独自に開催されたら面白そうなのにという意見もいただいた。難易度を下げた内容でやって欲しい、という意味かもしれない。実はシェル芸勉強会コワイけど興味ある、という方々が福岡にはまだいらっしゃるのかもしれない。