前回に引き続き鬼の忙しさが続いていたが、忙しさに切れ目・・・しかし本当に若干の切れ目・・・なんとかシェル芸勉強会の福岡サテライトを開催することができた。今回も参加いただきありがたや。会場は今回もAIP Cafe。
午前中は会社の会議の後、昼からはシェル芸地獄というなかなかハードな一日だった。10月になったけど昼は暑いよ。今回は総勢4人の参加者が集った。久しぶりの参加の方もいらっしゃった。
勉強会募集サイト
本家東京会場募集
大阪サテライト会場募集
福岡サテライト会場募集
イベント報告関連
今回のTLはどうだったのかな?
(上田会長による)jus共催 第31回朝からだと疲れるから午後からでええじゃろシェル芸勉強会の報告
jus共催 第31回朝からだと疲れるから午後からでええじゃろシェル芸勉強会の報告 | 上田ブログ
(上田会長による)Togetterまとめ
(くんすとさんによる)大阪サテライト会場の報告
午後の部
ということで今回は午後の部のみ。今回もイントロのスライドとか準備出来ず。せっかくなので持ってきたSoftware Design 9月号と10月号の宣伝をしたくらいだ。
こんなリスケジュールは嫌だ!という時に便利な?シェル関数作って投稿しましたよ(・ω・)ノ #gihyo #sd #シェル芸 pic.twitter.com/xfMRo4HQjv
— ぱぴろんちゃん👓 (@papiron) 2017年9月29日
今回の問題と解答は、下記の上田さんブログを参照のこと。上田さんのブログがついにbashCMS
へと移植されたようだ・・・ざわ・・・ざわ・・・
jus共催 第31回朝からだと疲れるから午後からでええじゃろシェル芸勉強会の報告 | 上田ブログ
問題が難しい場合は関連情報の解説や補足を重視して、今回も福岡サテライトなりのペースで進めていくぞい。
Q1
行をまたいだ置換の問題。工夫すればsed
で出来そうだがわからん・・・解答例を後から見ることにして、福岡では補足や解説が重要なのでsed
の後方参照やy
コマンド、拡張正規表現などの説明をした。後方参照出来る数は9個までだよとか。
# こんな感じで\( \)で囲った部分を\1\2で順番に参照出来るよ $ echo 123-45 | sed 's/^\(...\)-\(..\)/\1\2/' 12345 # GNU sedの-rオプションで拡張正規表現が使える。参照したい部分の囲みにバックスラッシュが不要。 $ echo 123-45 | gsed -r 's/^(...)-(..)/\1\2/' 12345 # yコマンドで変換だぞ $ echo 12345 | sed 'y/12345/abcde/' abcde $ echo 12345 | sed 's/12345/a/' a # trコマンドでも出来る。sedより高速だが動きが違う部分も。 $ echo 12345 | tr '12345' 'abcde' abcde $ echo 12345 | tr 12345 a aaaaa
解答例ではPerl正規表現のルックアラウンドアサーションを使うということだった・・・復習せにゃ。Perlの正規表現はPCREとしてライブラリで提供されており、PHPやApache HTTP Serverなどでも利用可能だよとか補足解説。
PCRE - Perl Compatible Regular Expressions
Q2
上の行に合わせたインデントをする。Vimのインデントコマンド=
で出来ないか?と思ったが、わての実力では出来なかった・・・
Vimでやっている人がいた。
vim だと qqywq/^\*@q/^\*@q/^\*@q/^\*@q でできるけど汚い #シェル芸
— のぎろ (@nogiro_iota) 2017年10月7日
ちなみにJavaScriopt(node)で解いている人もいて、もう意味がわからない。
JSならば、こうでしょうか??https://t.co/LVytgMNkzL#シェル芸
— ぷる@就活は来年から再始動 (@butackle66) 2017年10月7日
Q3
問題の図形を見て素数がすぐに出てくるのは変態。シェル芸界隈では定番になってきているが福岡サテライトではまだ十分知られていないので、素数列挙の定番ワンライナーを解説。
$ seq 1 20 | gfactor | awk 'NF==2{print $2}' 2 3 5 7 11 13 17 19
後はawk
で頑張ればなんとかなりそう。ということで最終的には会長の解答に。
Q4
福岡サテライトの参加者は、ASCIIコードやバイナリデータの扱いに慣れていない方が多かったので補足解説。
# まずはマニュアルを見て見る $ man ascii # odコマンドでASCIIコードを16進数表記 $ echo -n ABCabc | od -t x1c 0000000 41 42 43 61 62 63 A B C a b c 0000006 # BSD版だとマルチバイトに対応してるよ。 $ echo -n おはようございます | od -t x1c 0000000 e3 81 8a e3 81 af e3 82 88 e3 81 86 e3 81 94 e3 お ** ** は ** ** よ ** ** う ** ** ご ** ** ざ 0000020 81 96 e3 81 84 e3 81 be e3 81 99 ** ** い ** ** ま ** ** す ** ** 0000033 # vim付属のxxdコマンドで16進数表記。 $ echo -n おはようございます | xxd 00000000: e381 8ae3 81af e382 88e3 8186 e381 94e3 ................ 00000010: 8196 e381 84e3 81be e381 99 ........... # -uオプションで10進数表記 $ echo -n おはようございます | od -t u1c 0000000 227 129 138 227 129 175 227 130 136 227 129 134 227 129 148 227 お ** ** は ** ** よ ** ** う ** ** ご ** ** ざ 0000020 129 150 227 129 132 227 129 190 227 129 153 ** ** い ** ** ま ** ** す ** ** 0000033 # -bオプションで2進数表記。ビット列が見えるよ。 $ echo おはようございます | xxd -b 00000000: 11100011 10000001 10001010 11100011 10000001 10101111 ...... 00000006: 11100011 10000010 10001000 11100011 10000001 10000110 ...... 0000000c: 11100011 10000001 10010100 11100011 10000001 10010110 ...... 00000012: 11100011 10000001 10000100 11100011 10000001 10111110 ...... 00000018: 11100011 10000001 10011001 00001010 ....
Q5
Q4でのASCIIコードやバイナリデータに解説してたら、あまり時間が無くなる。解答例に出てきたプロセス置換について解説をした。
# 2つのコマンドの出力結果をdiffで比較 1d0 < 1 3a3 > 4
シェルの本質はコマンドの実行とプロセス管理、ファイルをベースとしたデータ入出力の管理、といったことを解説。補足として/dev/urandom
、/proc
ファイル、bash
のtcp通信機能など、ファイルをベースとした機能も。
# 乱数取得のワンライナー。trの-dcオプションについても補足解説。 $ cat /dev/urandom | LANG=C tr -dc '0-9' | fold -w 10 | head 5185330642 4941724968 8040182629 4953975155 7776003351 2268161449 3516241602 2661394339 7045619931 7999489264
Q6
UTF-8な日本語ひらがなを小文字に変換する問題。参加者から文字コードをズラせばいいんじゃない?という意見が出る。じゃあ確認してみよう。
$ echo -n あぁ | xxd -p | fold -w 6 e38182 e38181
ということで、3バイト毎にまとめてコード番号を1引けば良さそう。ということで考えた解答例がこちら。やっと1問だけちゃんとした解答が出せた・・
$ echo -n あいうえお | xxd -p -u | fold -w 6 | sed 's/$/ - 1/' | (echo 'obase=10;ibase=16'; cat) | bc | (echo 'obase=16'; cat) | bc | xxd -p -r ぁぃぅぇぉ
bc
コマンドについては知られていなかったので補足解説。bash
やbc
自体の履歴機能が使えるので、繰り返し計算する時の電卓替わりにも便利だよ。
Q7
アニメーションを作る問題。解答を作るのは断念。
そもそも端末でアニメーションを作るにはどうすればいいか?という解説をした。例えば1秒毎に@
が一つずつ伸びていくにはこんな感じとか。
# まずはコマンド列を作成する $ seq 3 | awk '{for(i=1;i<$1;i++){printf "@"}print ""}' | sed 's/^/clear; echo /' | sed 's/$/; sleep 1;/' clear; echo ; sleep 1; clear; echo @; sleep 1; clear; echo @@; sleep 1; # 上記のコマンドをシェルに流し込んで実行。 $ seq 3 | awk '{for(i=1;i<$1;i++){printf "@"}print ""}' | sed 's/^/clear; echo /' | sed 's/$/; sleep 1;/' | sh
Q8
全角5文字以内で折り返す問題。ギブアップ・・・
Q9
スクレイピングの問題。CSVにするのは諦め元素記号だけを抽出するものを作った・・・敗北感。
$ curl -s http://www.gadgety.net/shin/trivia/ptable/ | sed -n '/<tr /,/<\/tr>/p' | grep font | grep '<a href="' | grep -o '<a href="[^"][^"]*\.html">[^<>][^<>]*</a>' | sed 's/<[^<>]*>//g' H He Li Be (省略) Fm Md No Lr
午後の部終了後
スライドの準備は出来なかったが、参加者の方でTwitterでxargs
コマンドの使い方を色々悩んでた方がいらっしゃったのもあり、改めてxargs
コマンドについて基本からおさえる話をした。
xargsについて
配列的なデータを扱う
- 配列的な文字列データに対して、コマンド処理をまとめて実行する時に使う
- 区切り文字はスペース、タブ、改行、EOF
使い方の基本例
$ find dir -type f | xargs file $ echo {1..5} | xargs printf '%05d\n' 00001 00002 00003 00004 00005
コマンドを指定しない場合は、暗黙的にechoが実行される。
$ seq 10 | xargs -n 2 1 2 3 4 5 6 7 8 9 10
どんな処理をするコマンドか?
xargs
はHaskellやRuby、JavaScriptのmapに似ており、配列的なデータに対して繰り返し同じ処理を施す。配列内の数字を2倍にする処理を考える。
# xargsコマンド $ seq 1 5 | xargs -I@ expr @ \* 2 2 4 6 8 10 # Ruby $ pry [1] pry(main)> [1,2,3,4,5].map do |i| i*2 end => [2, 4, 6, 8, 10] # JavaScript $ node > [1,2,3,4,5].map((n)=>{return n*2}) [ 2, 4, 6, 8, 10 ] # PHP $ psysh >>> array_map(function($num){return $num*2;},[1,2,3,4,5]) => [ 2, 4, 6, 8, 10, ]
オプション
-nオプション
一度に処理する数を指定-Iオプション
通常はコマンド列の最後に渡すが、埋め込む文字列を指定して自由にコマンド列を作成可能。
$ seq 5 | xargs -I@ gdate -d '@ day' +%F 2017-10-08 2017-10-09 2017-10-10 2017-10-11 2017-10-12
- -0オプション
ディレクトリ名やファイル名に空白などがある場合に便利。
$ find 'VirtualBox VMs' -print0 | xargs -0 file
複数のコマンドを実行するには?
複数のコマンドやパイプなどは実行出来ないが、sh
やbash
の-c
オプションを使うことでカバー可能。1秒毎に1カウントアップするワンライナーがこちら。
$ seq 10 | xargs -I@ sh -c 'echo @; sleep 1;' 1 2 (省略) 9 10
- -Pオプション
並列処理が可能。「真・マイナンバーシェル芸」の記事を紹介。
あとはImageMagickとの実用的な組み合わせで、画像ファイルを再帰的に選択してフォーマットの変換やサムネイル作成の処理をするワンライナーを紹介したり。
# PNG=>JPGへフォーマット変換 $ find * -type f -name '*.png' | sed 's/\.png//' | xargs -I@ convert @.png @.jpg # 長辺が100x100ピクセル以内のサムネイル画像を作成。ファイル名に-sを追加。 $ find * -type f -name '*.png' | sed 's/\.png//' | xargs -I@ convert -geometry 100x100 @.png @-s.png
他にはcurl
コマンドでデカイデータをPOSTする際にコマンドライン長制限の問題が出て困った、という話題が上がった。これについてはデータをファイルから読んで出来るのでは?と予測。
curl
のマニュアルを見るとファイル名に@
を付けて指定すれば良さそう。ググって調べて見るとファイル名に@
を付ける方法で良さそうだ。
今回も疲れた!参加者の方々お疲れ様!!