〜2016年6月中旬〜
anagol的にはつい-sまでしちゃうが、それは不要。
% jot -r 10 1 100 | xargs -n 5 | jq -R -r 'split(" ")|map(tonumber)|sort|@sh' 6 29 34 59 62 27 30 67 80 82
sort_byを使う方法も。
% jot -r 10 1 100 | xargs -n 5 | jq -R -r 'split(" ")|sort_by(tonumber)|join(" ")' 2 5 9 32 90 1 7 76 87 95
というわけでいろいろ探してみた。
% for i in inet-ip.info ifconfig.io ifconfig.es globalip.me ipcheck.ieserver.net ifconfig.co ipv4bot.whatismyipaddress.com httpbin.org/ip;do echo -n "$i: "; /usr/bin/time -f '%E %C' curl -s $i > /dev/null; done 2>&1 | sort -k2,2 | column -t globalip.me: 0:00.23 curl -s globalip.me ifconfig.io: 0:00.25 curl -s ifconfig.io ipv4bot.whatismyipaddress.com: 0:00.28 curl -s ipv4bot.whatismyipaddress.com ipcheck.ieserver.net: 0:00.36 curl -s ipcheck.ieserver.net inet-ip.info: 0:00.45 curl -s inet-ip.info httpbin.org/ip: 0:00.46 curl -s httpbin.org/ip ifconfig.es: 0:00.61 curl -s ifconfig.es ifconfig.co: 0:00.64 curl -s ifconfig.co
どれでも同じようなもんだけど、httpbin.org/ipはjson形式だったりするので注意。
シェル芸で使いたい jqイディオム - Qiitaを見ててあれと思った。
printfコマンドで最後の改行を削っておかないと、行配列の最後に空の要素が入ってしまう
そんなことないような。
% echo foo | jq -R -s 'split("\n")' [ "foo" ]
ああ、jq 1.5だとsplitの挙動が違うのか。
% echo foo | jq-1.5 -R -s 'split("\n")' [ "foo", "" ]
これはうっとうしいかも。
シェル芸で使いたい jqイディオム - Qiita
CSVの読み込みで全体を配列としないならこういう方法もある。
まず-sを削除。改行でsplitする必要がなくなりmapも不要になる。
しかも最後の改行はつかなくなるので前段の処理も不要。
% echo $'foo1,bar1,hoge1\nfoo2,bar2,hoge3' | jq-1.4 -R 'split(",") | {"fld1": .[0], "fld3": .[2]}' { "fld1": "foo1", "fld3": "hoge1" } { "fld1": "foo2", "fld3": "hoge3" } % echo $'foo1,bar1,hoge1\nfoo2,bar2,hoge3' | jq-1.5 -R 'split(",") | {"fld1": .[0], "fld3": .[2]}' { "fld1": "foo1", "fld3": "hoge1" } { "fld1": "foo2", "fld3": "hoge3" }
1.4でも1.5でも結果は同じ。
またまた シェル芸で使いたい jqイディオム - Qiitaの登場で恐縮ではあるけど、CSVの読み込みで最後の改行削除で、
cat sample.csv | printf %s "$(cat)"
していた。これはbashでは動くがzshでは動かない。
% echo foo | printf %s "$(cat)" cat: -: 入力/出力エラーです
どうもpipe処理よりも先にコマンド置換が行なわれるようで。
というわけで後で評価されるようにしてあげればzshでも動く。
% echo foo | { printf %s "$(cat)" } | od -c 0000000 f o o 0000003 % echo foo | ( printf %s "$(cat)" ) | od -c 0000000 f o o 0000003
AWS Lambdaのblueprintに従うとslackにcustom slashコマンドが追加されることになる。
これが曲者でslashコマンドって結構使い辛い。
まずecho backがない。何を打ったか記録に残らない。
まあそれなら応答に入力も含めればよさげだが、
なぜかコマンドを実行した自分にしか表示されない。
というわけでこれを利用してchatopsはちょっと無理がある。
slash commandだと無理があるならどうすればいいか。
実はOutgoing WebHooksを使えばほとんど同じことができる。
こちらはチャンネル指定もできるし、"/"をつける必要もない。
もちろん普通のメッセージになるのでecho backもするし、
応答は自分だけじゃなくそのまま普通のbotoのメッセージとして処理される。
ちょっとquery parameterが違うだけなのでblueprintからの変更も少ない。
完璧だ。
【問題】第23回梅雨でモワッとしたシェル芸勉強会 – 上田ブログ
というわけで梅雨とは思えない暑さの中行ってきた。
今回はオープンなデータを扱うawkまつりだった。
最大の敵はファイル名の長さだった。twitter的には非常につらい。
これは準備。YYYYMM 上陸頻度という形式。
後々の問題のためにはYYYY MMのように空白があったほうがよかったいう意見がちらほら。
年ごとなので上位4文字をキーにして頻度を集計。
CSVのほうは上陸してない年は0ではなく空文字なので、
$NF+0しておく必要がある。+$NFでもいい。
cmpなので何も表示されなければok。
% awk '{h[substr($1,1,4)]+=$2}END{for(i in h)print i,h[i]}' monthly_typhoon|sort|cmp - <(awk -F, 'NR>1{print $1,+$NF}' landing.csv)
月ごとなので年は不要。ここでも+することで0-prefixを削除している。
% awk '$2{m[+substr($1,5)]++}END{for(i=1;i<=12;i++)printf "%2d %5.2f%%\n", i,m[i]*100/NR*12}' monthly_typhoon 1 0.00% 2 0.00% 3 0.00% 4 1.54% 5 3.08% 6 13.85% 7 40.00% 8 63.08% 9 63.08% 10 20.00% 11 1.54% 12 0.00%
landing.csvを使うとこんな感じ。-F,することでNFが,の数になり、それが最初の月になる。
% sed 's/,[1-9].*//' landing.csv | awk -F, 'NR>1&&NF<14{print NF}'|sort -n|uniq -c 1 4 2 5 9 6 21 7 19 8 7 9 2 10
monthly_typhoonだったらこんな感じ。また+だ。
% awk '$2&&!a[substr($1,1,4)]++{print +substr($1,5)}' monthly_typhoon|sort -n|uniq -c % sed 's/\B/ /4' monthly_typhoon | awk '$3&&!a[$1]++{print +$2}'|sort -n|uniq -c
landing.csvを使うのは禁止。
xargsを使い1年を1行にして、行頭のだけ残してYYYYMM を削除。
YYYY01 000000000000が消せればそれが上陸しなかった年。
% xargs -n24 < monthly_typhoon | sed -n 's/ [0-9]\{6\} //g;s/01 0*$//p' 1984 1986 2000 2008
ひねりなし。
% cut -f1 -d' ' hittakuri|sort|uniq -c 56 大阪市中央区 9 大阪市住之江区 29 大阪市住吉区 53 大阪市北区 23 大阪市城東区 7 大阪市大正区 20 大阪市天王寺区 33 大阪市平野区 8 大阪市旭区 22 大阪市東住吉区 18 大阪市東成区 17 大阪市東淀川区 1 大阪市此花区 22 大阪市浪速区 31 大阪市淀川区 6 大阪市港区 31 大阪市生野区 9 大阪市福島区 28 大阪市西区 37 大阪市西成区 8 大阪市西淀川区 15 大阪市都島区 19 大阪市阿倍野区 6 大阪市鶴見区
population_h27sepをpという連想配列に読み込む。
引数にf=1を挟むことでフラグとして使える。
-(標準入力)を読み込む前にf=1になる。
% cut -f1 -d' ' hittakuri|sort|uniq -c|awk '!f{p[$1]=$2}f{printf "%7.3f%% %s\n", $1*100/p[$2],$2}' population_h27sep f=1 -|sort -nr 0.059% 大阪市中央区 0.045% 大阪市北区 0.034% 大阪市西成区 0.034% 大阪市浪速区 0.031% 大阪市西区 0.027% 大阪市天王寺区 0.024% 大阪市生野区 0.022% 大阪市東成区 0.019% 大阪市住吉区 0.018% 大阪市阿倍野区 0.018% 大阪市淀川区 0.017% 大阪市東住吉区 0.017% 大阪市平野区 0.015% 大阪市都島区 0.014% 大阪市城東区 0.013% 大阪市福島区 0.010% 大阪市東淀川区 0.010% 大阪市大正区 0.009% 大阪市旭区 0.008% 大阪市西淀川区 0.007% 大阪市港区 0.007% 大阪市住之江区 0.005% 大阪市鶴見区 0.001% 大阪市此花区
cutでもawkでもいいと思うが、cutのほうが指定が簡単。
% cut -d' ' -f1-3,8-10 hittakuri|sort|uniq -d 大阪市北区 曾根崎 2丁目付近 2015年 4月 13日 大阪市北区 角田町 付近 2015年 11月 4日 大阪市淀川区 十三本町 1丁目付近 2015年 4月 16日
既遂が成功で手段が自転車とか。
/既遂/だとむだに0のときも足してるが場合分けしてないのでb[$7]++もいっしょに書ける。
% awk '{a[$7]+=/既遂/;b[$7]++}END{for(i in a)printf "%f %s\n", a[i]/b[i],i}' hittakuri | sort -nr 0.954225 自動二輪 0.942308 徒歩 0.920530 自転車 0.904762 自動車
nkfじゃなくても3バイト削るだけなのでBOMを消す方法はいろいろある。
tail -c +4 dd bs=1 skip=3 sed '1s/^\xEF\xBB\xBF//' LANG=ja_JP.UTF-8 sed '1s/^.//' LANG=C sed '1s/^...//'
LANGがja_JP.UTF-8ならBOMも1文字と見做される。
その前に一昨日の日記にQ1の解を書いてなかった。
% awk -F, 'NR>1{for(i=2;i<NF;i++)printf "%d%02d %d\n",$1,i-1,$i}' landing.csv > monthly_typhoon % head monthly_typhoon 195101 0 195102 0 195103 0 195104 0 195105 0 195106 0 195107 1 195108 0 195109 0 195110 1 % tail monthly_typhoon 201503 0 201504 0 201505 0 201506 0 201507 2 201508 1 201509 1 201510 0 201511 0 201512 0
jqでも無理をすればなんとかなるようで。
% jq -R -r 'split(",")|[.[0]+(. as $a|range(1;13)|"0\(.) "[-3:]+$a[.])|sub(" $";" 0")]|join("\n")|select(test("^\\d"))' landing.csv > monthly_typhoon
肝はrange(1;13)|"0\(.) "[-3:]の部分で、"%02d "を意味している。
% jq -n -c 'range(1;13)|"\(.) "' "1 " "2 " "3 " "4 " "5 " "6 " "7 " "8 " "9 " "10 " "11 " "12 " % jq -n -c 'range(1;13)|"0\(.) "[-3:]' "01 " "02 " "03 " "04 " "05 " "06 " "07 " "08 " "09 " "10 " "11 " "12 "
それをRubyで表現するとこんな感じ。
% ruby -anF, -e 'puts (1..12).map{|i|$F[0] + "%02d "%i + $F[i]}.map{|i|i.sub(/ $/, " 0")}.select{|x|x=~/^\d/}' landing.csv > monthly_typhoon