「第32回シェル芸勉強会:福岡サテライト」レポート
もう12月に突入したことが信じられない今日この頃ですが、朝の寒さにちょっと負けそうになりながらもシェル芸勉強会の福岡サテライトを開催させていただきました。会場は株式会社レスコ様の会議室です。会場担当の方、素敵な会場をご提供いただきありがとうございます。今回は総勢5人の参加者が集った。
問題作成と解説の上田さん、ありがとうございます。参加者の皆様お疲れ様でした。
勉強会の情報
勉強会主催者の上田さんが公開されているリンク集をご覧ください。
午前の部
午前中は鳥海さんによる、難しい領域にも勇敢に立ち向かう激・Perl講習会でした。最初から撃沈するオープニングでしたが、しばらくするとそれすらも前座であってまだ始まってすらいないことに気がつきます。内容的には下記のような処理が序の口という感じです。バックトラックの処理が見え見えになる、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
昼食
いつも行く餃子の王将とは違う中華料理店に行ってみたら、なかなか美味しかったですね。違う店を探索してみるのもええ気がします。
午後の部
今回も福岡サテライトなりのペースで、フォローや解説を重視しながら進めていきました。
Q1
抜けた数字を空行で飛ばして出力する問題。
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
— ぐれさん (@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
多分正規表現の問題だと思ったのですが、あえて文字コードを使った解答を考えました。
macOS付属のod
コマンドを使って文字コードの対応を確認してみます。ウムラウトは16進数c3
で始まる2バイト長の文字ですね。
macOSや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 (以下省略)
ちなみにGNU coreutils付属の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
macOS付属の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上で、福岡独自に開催されたら面白そうなのにという意見もいただきました。難易度を下げた内容でやって欲しい、という意味かもしれません。実はシェル芸勉強会コワイけど興味ある、という方々が福岡にはいらっしゃるかもしれません。