次ログ

次ログ

プログラミング系の記事多め。GoやJavaFXで自作のツールを公開したり、イラストを配布してます。

第41回 シェル芸勉強会振り返り

第41回シェル芸勉強会に参加した。初参加です。

まえがき

2019/4/27 (土)に「jus共催 第41回{ウン,ガク,}{チ,ト,}{,ン}{,コイン}{ブ,}{ラブラ, ハ,}{,イブ}{無,有}罪シェル芸勉強会」に参加してきたのでその振り返り。 この名称自体もシェル芸で[ブレース展開]という記法。これをechoしてみると以下のよう になる(※長すぎたので一部抜粋)。

echo jus共催 第41回{ウン,ガク,}{チ,ト,}{,ン}{,コイン}{ブ,}{ラブラ,ハ,}{,イブ}{無,有}罪シェル芸勉強会"\n" | wc -l

865

echo jus共催 第41回{ウン,ガク,}{チ,ト,}{,ン}{,コイン}{ブ,}{ラブラ,ハ,}{,イブ}{無,有}罪シェル芸勉強会"\n" | head

jus共催 第41回ウンチブラブラ無罪シェル芸勉強会
第41回ウンチブラブラ有罪シェル芸勉強会
第41回ウンチブラブライブ無罪シェル芸勉強会
第41回ウンチブラブライブ有罪シェル芸勉強会 +第41回ウンチブハ無罪シェル芸勉強会
第41回ウンチブハ有罪シェル芸勉強会
第41回ウンチブハイブ無罪シェル芸勉強会
第41回ウンチブハイブ有罪シェル芸勉強会
第41回ウンチブ無罪シェル芸勉強会
第41回ウンチブ有罪シェル芸勉強会

シェル芸勉強会の様子は Togetterにまとまっています。

午前の部

  • 文字コードの話
  • 文字列の結合、絵文字の結合、絵文字の色の変更ができる
  • UnicodeData.txtというファイルにユニコード文字のすべてが載っている

午後の部

8問のシェルの問題を片っ端からとくというもの。 問題に必要なファイルはこちらにある。 シェル芸のコマンドを実際に実行するなら、 あらかじめ以下のコマンドを実行して準備を整えておく。

git clone https://github.com/ryuichiueda/ShellGeiData
cd ShellGeiData/vol.41

問題の一覧はこちら。 以降は問題と自分の回答。

Q1

Q.次のファイルについて、2列目をキーにしてエクセルの横列の記号(A, B, ..., Z, AA, AB, ...のやつ)順に並べ替えてください。

$ cat excel
114514 B
1192296 AA
593195 CEZ
4120 TZ
999 QQQ

回答としては、以下のように出力されてほしい。テストの意図としては、文字列の長さも 考慮してソートしてほしい、というもの。

114514 B
1192296 AA
4120 TZ
593195 CEZ
999 QQQ

普通に sort コマンドで2カラム目を指定すると以下のようにソートされてしまう。

% sort -k2 excel 
593195 AA
114514 B
1192296 CEZ
999 QQQ
4120 TZ

文字列の長さのカラムを追加してソートするのが正攻法だろう。 僕の回答としては以下の通り。

% awk '{print $0, length($2)}' excel | sort -k3 -k2 | cut -d ' ' -f 1,2 
114514 B
593195 AA
4120 TZ
1192296 CEZ
999 QQQ

Q2

Q.次のファイルのレコードを干支順にソートしてください。

$ cat eto_yomi
申 さる
子 ね
寅 とら
卯 う
巳 み
辰 たつ
丑 うし
酉 とり
戌 いぬ
亥 い
午 うま
未 ひつじ

ただし、次のファイルを補助に使って良いこととします。

$ cat eto
子丑寅卯辰巳午未申酉戌亥

etoファイルの並びを利用してeto_yomiをソートするもの。まずは正攻法から。

sortなので素直にsortコマンドと別のファイルの中身を結合すると考えてjoinコマンドを 使用する。僕の回答としては以下の通り。

% grep -o . eto | nl | sort -k2 | join -1 2 -2 1 - <(sort eto_yomi) | sort -nk2 | cut -d ' ' -f 1,3
子 ね
丑 うし
寅 とら
卯 う
辰 たつ
巳 み
午 うま
未 ひつじ
申 さる
酉 とり
戌 いぬ

流れとしては下記の通り。

  1. grep -o で1行のデータを縦に並べて nl で番号の列を追加
  2. 後に控えている join は結合するフィールドが辞書順にソートされている必要がある ため、joinに指定するフィールドを辞書順にソート
  3. joinで結合。 -1 2-2 1 で1個めのファイルの2フィールド目と2個めのファ イルの1フィールド目を結合する
    1. eto_yomiも辞書順でソート
  4. 最初にnlで付与した番号を使い干支順にソートし直す
  5. cutで不要なフィールドの削除

シェル芸の非常に良いお題だったと思う。

次にgrepを使用した非常にコンパクトな例。初め僕は思いつかなかった。

% grep -o . eto | xargs -I@ grep @ eto_yomi
子 ね
丑 うし
寅 とら
卯 う
辰 たつ
巳 み
午 うま
未 ひつじ
申 さる
酉 とり
戌 いぬ
亥 い

すでに干支順でソートされているのでそのままgrepしてしまう、というもの。 こういうアプローチもあるのか、とまたシェル芸の知見が深まった。

Q3

Q.次のファイルのレコードを数字(第一フィールドの計算結果)が小さい順に並べてく ださい。

$ cat kim_calc
1+2+4 金正日
4*3 金正男
3-1-5 金日成
495/3 金正恩
0x1F 金正哲

これは割とすぐに思いついた。はじめは bc コマンドを使用していたが0x1fで失敗する のでbashの算術式を使用するようにしたら通った。 僕の回答としては下記の通り。

% cat kim_calc | while read -r e n; do echo $(($e)) $e $n; done | sort -nk1 | cut -d ' ' -f 2,3
3-1-5 金日成
1+2+4 金正日
4*3 金正男
0x1F 金正哲

Q4

Q.次のファイルはシフトJISのテキストですが、これを1) 辞書順、2) 数字の小さい順 、にソートしてください。出力もシフトJISとします。

$ cat sjis | nkf -g
Shift_JIS
$ cat sjis | nkf -wLux
123 ずんごるももう
31 こきたてひーひー
9 ほじぱんふんじこみ
2242 たまもとやろう

最初は試験の意図がわからなかったが、2つ結果を出力するだけでよかったらしい。 1の辞書順については下記の通り。

% cat sjis | nkf -wLux | sort
123 ずんごるももう
20 ほじぱんふんじこみ
2242 うえってきたかるとらまん
31 こきたてひーひー

2の数字の小さい順は手間が必要。このファイルの数値は全角数字なので数値ソートがで きない。なので修正してソートしてから復元する必要がある。僕の回答としては下記の通 り。

% cat sjis | nkf -wLux | sed 'y/1234567890/1234567890/' | sort -nk1 | sed 'y/1234567890/1234567890/'
20 ほじぱんふんじこみ
31 こきたてひーひー
123 ずんごるももう
2242 うえってきたかるとらまん

sedのyコマンドを使用して対応する数値を変換しているだけ。これも簡単な方だと思う。

Q5

Q.サイズの小さい順にソートしてください。

$ cat size 
2GB
1.2GB
40000MB
1000000000kB
0.4GB
410MB

はじめはsortのヒューマンリーダブルオプションでいけるか、と思ったがダメだった。

% cat size | sort --sort h
1000000000kB
410MB
40000MB
0.4GB
1.2GB
2GB

なんとキロバイト順、メガバイト順、ギガバイト順にソートされている。 仕方なくnumfmtで変換して元に戻した。

% cat size | tr -d B | tr k K | numfmt --from iec --to=none | paste - size | sort -nk1 | cut -f2
0.4GB
410MB
1.2GB
2GB
40000MB

Q6

Q.sleepと内部コマンドだけを使って次の数を小さい順にソートしてください。

$ cat nums
5.4
0.34
2.3
0.9
6

これも割とすぐ思いついた。 内部コマンドってなんだろうと思ったが help というコマンドを使えば分かる。 whileやforが使えたのと、非同期実行を使えば行ける。

% while read i; do (sleep $i; echo $i) & done < nums
0.34
0.9
2.3
5.4
6

Q7

Q.次のローマ数字をソートしてください。

$ cat roman
IV
XI
LXXXIX
IX
XLIII
XX
VIII

これは割と力づくだったが一応いけた。

% cat ShellGeiData/vol.41/roman \
| sed 's/IV/4 /g;s/XL/40 /g;s/IX/9 /g;s/I/1 /g;s/L/50 /g;s/X/10 /g;s/V/5 /g;s/ /+/g;s/+$//g;s/.*/echo $((&))/e' \
| paste - ShellGeiData/vol.41/roman \
| sort -nk1 \
| cut -f 2
IV
VIII
IX
XI
XX
XLIII
LXXXIX

numconvというコマンドの存在を他の方のシェルから知った。 それを使えば以下のように修正できる。

% cat roman | numconv | paste - roman | sort -nk1 | cut -f2
IV
VIII
IX
XI
XX
XLIII
LXXXIX

Q8

Q.次のファイルを辞書順にソートしてください。ただし、濁点がついているものが先に 来るようにしてください。できる人はワンライナー中で「かきくけこがぎぐげご」の文 字を使わないでください。

$ cat gagigugego 
かき氷
ぎ・おなら吸い込み隊
きつねうどん
ぐりこもりなが事件
きききりん
がきの使い
くその役にも立たない
げんしりょく発電
ごりらいも
こじんてきにはクソ
例
がきの使い
かき氷
ぎ・おなら吸い込み隊
きききりん
きつねうどん
ぐりこもりなが事件
くその役にも立たない
げんしりょく発電
ごりらいも
こじんてきにはクソ

これははじめどうしたら良いかわからなかったが、午前の部で話していた内容を使えばす ぐに解決できることがわかった。濁点文字を濁点なしの文字と濁点の結合文字に分割する ことでソート順序を変更するというもの。

% cat ShellGeiData/vol.41/gagigugego | uconv -x NFD | sort | uconv -x NFC
がきの使い
かき氷
ぎ・おなら吸い込み隊
きききりん
きつねうどん
ぐりこもりなが事件
くその役にも立たない
げんしりょく発電
ごりらいも
こじんてきにはクソ

LT会

まとめ

はじめてシェル芸勉強会に参加したけれど、新しい知見がいっぱいだった。 シェルはガリガリ普段から書いていたので、問題自体は割となんとかなった。 8問のうち7問は自力で解けた。解けなかったのはがぎぐげごのやつ。

何はともあれシェル芸勉強会、面白かった。 シェルはいろんな環境にあるし、ちょっとした作業をぱぱっと自動化できてやはり好きだし 今後も必要で有り続ける技術だと思うので、引き続き勉強は続けようと思う。

ただし100行を超えるような処理をシェルで書くのはやめよう。 素直に他の言語を使うべし(経験者は語る)。

以上。