第41回シェル芸勉強会に参加しました
参加しました
かんたんに感想を述べると、楽しかったです
午前
鳥海さんの文字コードシリーズ、第6回でした。今度こそ最終回だそうです。さみしい
お話はUnicode結合文字についてでした。
部品の集合とすることで、あらゆる文字を表現できるようにしているんですが、単純な比較ができない・1文字の判定が難しいなどの問題があります
# 回文なのでもとのまま echo おかしがすきすきすがしかお|rev おかしがすきすきすがしかお # uconv -x NFDでUnicode結合文字列へ分解できる。revすると濁点の位置がずれる echo おかしがすきすきすがしかお|uconv -x NFD|rev おかじかすきすきずかしかお
面白いですね。これらを正しく見るにはUnicodeの正規化(uconv -x NFC
)や書記素クラスタ(正規表現で\X
)などを使っていけばいいみたいです
# grep -o . だとばらばらになる $ echo -e た"\U3099" | grep -o . た ゛ # Unicode正規化 $ echo -e た"\U3099" | uconv -x NFC | grep -o . だ # 書記素クラスタ $ echo -e た"\U3099" | perl -C -lne "print for /\X/g" だ
他にもZWJや国旗絵文字シーケンス、ワタナベ難読化シェル芸で使った異体字セレクタなどが紹介されました。
特に国旗絵文字シーケンスは国旗難読化シェル芸の可能性を感じました。やるしかない
午後
「相当アレ」と告知がありましたが、sortのことだったようです。ふむ
問題と解答はここです
Q1
ファイルの2列目をキーにExcel順に並び替える問題
Excel順はA...Z,AA...ZZ,AAA...ZZZというやつですね。やってみます
$ cat excel | awk '{print $0, length($2)}'|sort -k3 -k2|awk '{print $1,$2}'
awk
を使ってキーの長さを出力しておき、それらを使って sort
コマンドで並び替えます。
-k[num]
を指定すると [num]
列目をキーに並び替えしてくれます。並べて書くこともできます。
LINQ的に書くと .OrderBy(3列目のキー).ThenBy(2列目のキー)
みたいな感じですね
Q2
干支の感じとその読みが書かれた eto_yomi
ファイルの中身を干支順に並び替える問題。干支の順番は eto
ファイルに書かれているので使ってもいいみたいです。やってみます
cat ShellGeiData/vol.41/eto_yomi <(grep -o . ShellGeiData/vol.41/eto) |awk 'NR<=12{x[$1]=$2}NR>12{print $1, x[$1]}'
やっていることは、まず eto_yomi
の1行目をキーに awk
の連想配列にぶち込みます(12個です)。その後 eto
の1文字をキーに連想配列を読み出して出力します。 sort
は使ってませんごめんなさい
この問題でこのパターンを覚えてしまったので以降でも出てきます
Q3
第一フィールドの計算結果が小さい順にレコードを並べ替える問題。やってみます
cat ShellGeiData/vol.41/kim_calc|awk '{print "echo \"$(("$1"))\"",$0}'|bash|sort -n|awk '{print $2,$3}'
awk
を使って echo $((第一フィールド)) 第一フィールド 第二フィールド
という文字列を作ります。 これを bash
に流し込んでやると第一フィールドの計算値がわかるので、それをキーに sort
し出力を整えて終わりです
この問題では sed
の s///e
が話題になったのでそっちもやってみます
$ cat ShellGeiData/vol.41/kim_calc|sed 's/^.* /echo "$((&))" &/e'|sort -n|awk '{print $2,$3}'
コマンドの生成と実行が sed
内で完結するのでシンプルになりますね
Q4
Shift-JISで書かれたファイルを1) 文字列としてソート 2) 第一フィールドの数字が小さい順にソート する問題。出力もShift-JISで出すこと。
1)はまだいいですが、2)は数字が全角で書かれているので何か変換しないとダメそうですね。やってみます
1) nkf ShellGeiData/vol.41/sjis | sort | iconv -t sjis 2) nkf -Z ShellGeiData/vol.41/sjis |sort -n|uconv -x Halfwidth-Fullwidth|sed 's/ / /'|iconv -t sjis
まずは1) からです。とりあえず nkf
でUTF8に変換します。文字列順にソートすればいいので普通に sort
します。そのあと iconv
でShift-JISにして終わりです。
この問題、僕もそうだったのですが一度UTF8に変換する解答が多かったです。しかし、並び替えるだけならその必要もなく…
1 別解) LANG=C sort ShellGeiData/vol.41/sjis
でいいわけですね。
次に2) です。今度は全角⇔半角の変換してやる必要がありそうです。 nkf
の -Z
がどんなことをするのか、 nkf --help
を見てみます。
Z[0-4] Default/0: Convert JISX0208 Alphabet to ASCII 1: Kankaku to one space 2: to two spaces 3: HTML Entity 4: JISX0208 Katakana to JISX0201 Katakana
$ echo "A1@"|nkf -Z0 A1@
デフォルトの -Z0
はJISX0208のアルファベットやらをASCIIにしてくれるみたいですね
これで第一フィールドが半角数字になったので、 sort -n
でうまく並べ替えることができます。
次に uconv
で半角にした数字を全角へ戻します。 -x Halfwidth-Fullwidth
を指定するとその通り半角から全角へ変換してくれます。
最後に uconv
に巻き込まれた半角スペースをもとに戻して終わりです
Q5
size
というファイルにはデータのサイズがいくつか書かれていて、これをサイズ順に並べ替える問題。
この問題の厄介なところは 410MB
とか 0.4GB
とかが混在するところですね。やってみます
paste <(cat ShellGeiData/vol.41/size|sed 's/B//g;s/G/E9/g;s/M/E6/g;s/k/E3/g') ShellGeiData/vol.41/size|sort -g|awk '{print $2}'
paste
の部分だけ実行するとどうなるか見てみます
$ paste <(cat ShellGeiData/vol.41/size|sed 's/B//g;s/G/E9/g;s/M/E6/g;s/k/E3/g') 2E9 2GB 1.2E9 1.2GB 40000E6 40000MB 1000000000E3 1000000000kB 0.4E9 0.4GB 410E6 410MB
sort
に使うキーとして、SIを指数表記(E9とか)へ変換したものを追加します。ここで sort -g
を使うと指数表記も解釈して並び替えてくれます。その後整形して終わりです
一応 sort
の -g
がどんなことをしてくれるのか、sort --help
を見てみます
-g, --general-numeric-sort compare according to general numerical value
general numerical value
ってなんだよって話ですね。このstackoverflowの質問の回答にもありますが、-g
は低速になるが指数表記を解釈でき、浮動小数点として並び替えてくれるようですね。なるほどこれはいいですね
Q6
sleep
と組み込みコマンドのみを使って nums
を並び替える問題
スリープソートと言うやつらしいですね。やってみます
while read l; do (sleep $l && echo $l)& done < ShellGeiData/vol.41/nums
while
echo
read
は組み込みです。 これらを使って sleep 時間 && echo 時間
というコマンドをほぼ同時に起動し、スリープソートを行います
こういう問題は難読化してやればごまかせるかもしれないですね
$ : "$(sleep --version)" && ${_:0:1}${_:12:2}${_:16:1} ./ShellGeiData/vol.41/nums 0.34 0.9 2.3 5.4 6
そんなに高度なことはしてないので読んでみるといいかもしれません
Q7
ローマ数字をソートする問題
paste <(numconv < ShellGeiData/vol.41/roman) ShellGeiData/vol.41/roman|sort -k1n|awk '{print $2}'
時間中に numconv
というコマンドを知ったのでそれでやりました。すんごいですよこのコマンド
ちなみにOCaml製のCLIツールにromanってやつもあります。ggって見つけたのはこっちだったんですが、環境が入ってなかった
Q8
文字列を並び替える問題。ただし「か」より「が」が前で「き」より「ぎ」が前になるようにすること、ひらがなを使わないこと
午前中にやったことを使えばできそうですね
cat ShellGeiData/vol.41/gagigugego|uconv -x NFD|sort|uconv -x NFC
最初に提出したのは uconv -x NFC
無し版だったんですが、これはどうやらお行儀が悪いらしいです。確かによくなさそうですね。
ところでこの解答どうやら想定されていたみたいなんですが、環境によってはダメ。ということでした。難しいですね
ひらがなを使ったバージョンも作ってみました。Q2で使ったパターンと同じですが
echo がかぎきぐくげけごこ|grep -o .|cat <(sed 's/^./& &/g' <ShellGeiData/vol.41/gagigugego) -|awk 'NR<=10{x[$1]=x[$1]" "$2}NR>10{print x[$1]}'|xargs -n1
LT
今回もLTさせていただきました!聞いてくださった皆様ありがとうございました!テーマは「CLIからドット絵画像を出力」です
https://github.com/xztaityozx/t2p
入力文字列からテーブルを使って色を決定、ドット絵へ変換します。半日クオリティです
終わりに
今回もとても楽しかったです!運営の皆様ありがとうございました!あと素材にしてすいませんでした