ということで、第17回シェル芸勉強会は、ジュンク堂を乗っ取ってのトークイベントの中で行われたようだ。Ustream配信はされていたが、今回は仕事でテンパっていて参加出来ず・・・
ようやく少し精神的にも余裕が出た気がする?ので、シェル芸勉強会の回答をば。問題と回答については、USP友の会会長様のページをご覧あれ。
【問題のみ】第17回ジュンク堂はシェル芸が乗っ取った勉強会 – 上田ブログ
【問題と解答】第17回ジュンク堂はシェル芸が乗っ取った勉強会 – 上田ブログ
今回の勉強会は下記の本の出版を記念してのトークイベント内で行われた。なので回答もAWKを多用すべきなんろうが、あんまり使ってないのでご容赦を・・・awkを使った例は、上記会長の解答例をご覧あれ。awkは処理速度も速いし色々便利。
トークイベントについてはこちらのTogetterにて。
下記解答例の実行環境は、MacでOSX Yosemite、HomebrewでGNU grep(ggrep)とrbenv、Open usp Tukubai。Rubyはruby 2.2.2p95。
Q1
第一フィールドをキーにして、同じキーで横へ並べる。
$ cat data1
a 1
b 4
a 2
a 3
b 5
Tukubai使うと超簡単に・・・
$ cat data1 | sort | yarr num=1
a 1 2 3
b 4 5
次にJSON形式で出力。上記のTukubai芸からのRuby芸。Rubyの配列連結を使えば割と簡単?
$ cat data1 | sort | yarr num=1 |
ruby -alne 'BEGIN{a=[]};a<<$F[0]+":["+$F[1..-1]*","+"]";END{puts "{"+a*","+"}"}'
{a:[1,2,3],b:[4,5]}
Q2
データの中で同じ行のものを探し出し、行番号を出力。
$ cat data
0.5937836043 0.4644710001
0.3637036697 0.5593602512
0.5655269331 0.6793148112
0.7804610574 0.2905477797
0.3637036697 0.5593602512
得意技になりつつある、GNU grepのフィルタモードと、bashのProcess Substututionの合わせ技。これにTukubaiをブレンドすれば意外とスッキリ。Process Substututionはチョット反則な気がするが、まあいいよね?
$ cat data | sort -k2,3 | uniq -u |
ggrep -v -f - <(juni data) | self 2/NF 1 | yarr num=2
0.3637036697 0.5593602512 2 5
【追記】もっと簡単にこんなのでもよかった。
$ cat data | sort | uniq -d | ggrep -nf - data
2:0.3637036697 0.5593602512
5:0.3637036697 0.5593602512
Q3
JSON形式のデータについて、キーに対応した配列内の数値を合計。
$ cat json
{"a":[1,2,3],"b":[4,5]}
1行1レコード空白区切りにしてしまえばこっちものでゴザル。
$ cat json | grep -o '"[ab]":\[[^]]*\]' | tr '":[],' ' ' |
ysum num=1 | awk '{print $1,$NF}'
a 6
b 9
Ruby芸。JSON ModuleとArray#inject使えば簡単になっちゃうので、問題の意図に反している気が・・・
$ cat json |
ruby -r json -ne 'JSON.load($_.chomp).each{|l| puts "#{l[0]} #{l[1].inject(:+)}"}'
a 6
b 9
Q4
IPv6ゼロパディングの闇にトライなお題。ちなみにこのお題、シェルプログラミング実用テクニックにも記載があるので、興味がある方はご購入をば。
え〜ゴメンナサイゴメンナサイ、Rubyで反則使ってゴマカシ・・・・
$ echo 2001:db8::9abc |
ruby -r 'ipaddr' -ne 'puts IPAddr.new($_.chomp).to_string'
2001:0db8:0000:0000:0000:0000:0000:9abc
$ echo ::1 |
ruby -r 'ipaddr' -ne 'puts IPAddr.new($_.chomp).to_string'
0000:0000:0000:0000:0000:0000:0000:0001
おまけで逆変換。
$ echo '2001:0db8:0000:0000:0000:0000:0000:9abc' |
ruby -r 'ipaddr' -ne 'puts IPAddr.new($_.chomp).to_s'
2001:db8::9abc
$ echo 0000:0000:0000:0000:0000:0000:0000:0001 |
ruby -r 'ipaddr' -ne 'puts IPAddr.new($_.chomp).to_s'
::1
Q4のRuby芸のポイントはこちら。
- IPAddr#to_s ショート形式で出力(ゼロパディング無)
- IPAddr#to_string ロング形式で出力(ゼロパディング有)