〜2014年9月下旬〜
さいたま市の1時間ごとの気温データはとりあえず20日と21日だとこんな感じ。
2014-09-20 01:00 18.5 2014-09-20 02:00 18.0 2014-09-20 03:00 18.1 2014-09-20 04:00 17.5 2014-09-20 05:00 17.5 2014-09-20 06:00 17.5 2014-09-20 07:00 18.0 2014-09-20 08:00 18.6 2014-09-20 09:00 18.7 2014-09-20 10:00 19.0 2014-09-20 11:00 19.4 2014-09-20 12:00 19.7 2014-09-20 13:00 20.2 2014-09-20 14:00 20.5 2014-09-20 15:00 20.7 2014-09-20 16:00 20.9 2014-09-20 17:00 20.5 2014-09-20 18:00 19.6 2014-09-20 19:00 17.8 2014-09-20 20:00 17.7 2014-09-20 21:00 17.0 2014-09-20 22:00 15.8 2014-09-20 23:00 14.9 2014-09-20 24:00 14.4 2014-09-21 01:00 13.8 2014-09-21 02:00 13.3 2014-09-21 03:00 13.0 2014-09-21 04:00 12.5 2014-09-21 05:00 12.4 2014-09-21 06:00 12.0 2014-09-21 07:00 14.6 2014-09-21 08:00 17.5 2014-09-21 09:00 20.3 2014-09-21 10:00 22.1 2014-09-21 11:00 23.7 2014-09-21 12:00 24.5 2014-09-21 13:00 25.2 2014-09-21 14:00 25.6 2014-09-21 15:00 24.7 2014-09-21 16:00 25.2 2014-09-21 17:00 24.2 2014-09-21 18:00 23.1 2014-09-21 19:00 22.7 2014-09-21 20:00 21.6 2014-09-21 21:00 21.1 2014-09-21 22:00 21.2 2014-09-21 23:00 20.9 2014-09-21 24:00 18.6
ここから日ごとの最低気温をもとめるにはどうすれば簡単にできるかというのが今日のお題。
awkを使って日ごとの最小値をなんてやるのも結構面倒。
ここはsortしてuniqしてしまうのが簡単。
日付と気温をキーにしてsortし、日付だけでuniqする。
これで日付ごとの先頭にあるものだけ残る。
% sort -k1,1 -k3,3n amedas.log | uniq -w10 2014-09-20 24:00 14.4 2014-09-21 06:00 12.0
もちろん逆順にすれば最高気温になる。
% sort -k1,1 -k3,3nr amedas.log | uniq -w10 2014-09-20 16:00 20.9 2014-09-21 14:00 25.6
uniqに-wオプションがない場合はawk '$1!=l;{l=$1}'でいける。
% sort -k1,1 -k3,3n amedas.log | awk '$1!=l;{l=$1}' 2014-09-20 24:00 14.4 2014-09-21 06:00 12.0
Nexus 7がすっかり工場出荷状態に戻ってしまったので、
PCにつないでもadb shellができなくなった。
設定のタブレット情報をいっぱいタップするのは覚えていたが、
なぜかそれだけでいいと思い込んでしまい、
しばらくなんでno deviceになるのか悩んだ。
開発者向けオプションのUSBデバッグをチェックしないと意味がない。
こういう1回やればok的なものは中々思い出せないもんだな。
先日awkでuniqの処理をさせたのは忠実にuniqコマンドと同じように
前の行と同じだったらという処理にしたが、
rubyのuniqのように離れていても重複を取り除きたいときは連想配列を使う。
% sort -k3,3n amedas.log 2014-09-21 06:00 12.0 2014-09-21 05:00 12.4 2014-09-21 04:00 12.5 2014-09-21 03:00 13.0 2014-09-21 02:00 13.3 2014-09-21 01:00 13.8 2014-09-20 24:00 14.4 2014-09-21 07:00 14.6 2014-09-20 23:00 14.9 2014-09-20 22:00 15.8 2014-09-20 21:00 17.0 2014-09-20 04:00 17.5 2014-09-20 05:00 17.5 2014-09-20 06:00 17.5 2014-09-21 08:00 17.5 2014-09-20 20:00 17.7 2014-09-20 19:00 17.8 2014-09-20 02:00 18.0 2014-09-20 07:00 18.0 2014-09-20 03:00 18.1 2014-09-20 01:00 18.5 2014-09-20 08:00 18.6 2014-09-21 24:00 18.6 2014-09-20 09:00 18.7 2014-09-20 10:00 19.0 2014-09-20 11:00 19.4 2014-09-20 18:00 19.6 2014-09-20 12:00 19.7 2014-09-20 13:00 20.2 2014-09-21 09:00 20.3 2014-09-20 14:00 20.5 2014-09-20 17:00 20.5 2014-09-20 15:00 20.7 2014-09-20 16:00 20.9 2014-09-21 23:00 20.9 2014-09-21 21:00 21.1 2014-09-21 22:00 21.2 2014-09-21 20:00 21.6 2014-09-21 10:00 22.1 2014-09-21 19:00 22.7 2014-09-21 18:00 23.1 2014-09-21 11:00 23.7 2014-09-21 17:00 24.2 2014-09-21 12:00 24.5 2014-09-21 15:00 24.7 2014-09-21 13:00 25.2 2014-09-21 16:00 25.2 2014-09-21 14:00 25.6 % sort -k3,3n amedas.log | awk '!a[$1]++' 2014-09-21 06:00 12.0 2014-09-20 24:00 14.4
のように2つだけ残る。日付順にはならなくなるが。
なんかやたらと長くなってしまった。
% ruby -e 'puts $<.sort_by{|x|x.split.values_at(0,2)}.uniq{|x|x.split[0]}' amedas.log 2014-09-20 24:00 14.4 2014-09-21 06:00 12.0
ほんとは気温をto_fする処理が必要だよなあ。もうちょっと寒くなったら。
syslogがやけにサイズがでかいので見てみるとこんなメッセージで埋まってた。
Sep 25 00:00:00 m kernel: [305350.490924] usb 2-1.2.3: new full-speed USB device number 91 using ehci-pci Sep 25 00:00:00 m kernel: [305350.898636] usb 2-1.2.3: device not accepting address 91, error -32 Sep 25 00:00:00 m kernel: [305350.971094] usb 2-1.2.3: new full-speed USB device number 92 using ehci-pci Sep 25 00:00:01 m kernel: [305351.378699] usb 2-1.2.3: device not accepting address 92, error -32 Sep 25 00:00:01 m kernel: [305351.378996] hub 2-1.2:1.0: unable to enumerate USB device on port 3 Sep 25 00:00:01 m kernel: [305351.519007] usb 2-1.2.3: new full-speed USB device number 93 using ehci-pci Sep 25 00:00:01 m kernel: [305351.591005] usb 2-1.2.3: device descriptor read/64, error -32 Sep 25 00:00:01 m kernel: [305351.767003] usb 2-1.2.3: device descriptor read/64, error -32 Sep 25 00:00:01 m kernel: [305351.943043] usb 2-1.2.3: new full-speed USB device number 94 using ehci-pci Sep 25 00:00:01 m kernel: [305352.015021] usb 2-1.2.3: device descriptor read/64, error -32 Sep 25 00:00:01 m kernel: [305352.195050] usb 2-1.2.3: device descriptor read/64, error -32 Sep 25 00:00:02 m kernel: [305352.370916] usb 2-1.2.3: new full-speed USB device number 95 using ehci-pci Sep 25 00:00:02 m kernel: [305352.778847] usb 2-1.2.3: device not accepting address 95, error -32 Sep 25 00:00:02 m kernel: [305352.851148] usb 2-1.2.3: new full-speed USB device number 96 using ehci-pci Sep 25 00:00:02 m kernel: [305353.258852] usb 2-1.2.3: device not accepting address 96, error -32 Sep 25 00:00:02 m kernel: [305353.259190] hub 2-1.2:1.0: unable to enumerate USB device on port 3 Sep 25 00:00:03 m kernel: [305353.403168] usb 2-1.2.3: new full-speed USB device number 97 using ehci-pci Sep 25 00:00:03 m kernel: [305353.475163] usb 2-1.2.3: device descriptor read/64, error -32
1秒間に8個とか吐かれりゃでかくもなるな。
USBのなにが原因がよくわからなかったが、usbに混じってhubという文字が。
これどっちも3文字だから見逃すって。
ハブを抜いたらおさまった。これが原因か。
なくても足りてるから抜いておこう。
リモート視聴とかFLACとかはどうでもいいが、DLNAアップロード機能が気になった。
Smart J:COM Boxからnanseへ保存できれば全部nasneで操作できるわけで。
まあ、そんな都合のいいことはできなかったが、
逆にnasneに保存されてる番組はSmart J:COM Boxで見られるようにはなった。
ひょっとしたら前からできてたかもしれないが、全然うれしくない。
qiitaに
bashのインストール方法が書いてあった。
それはまあいいとして、面白いのはfor文で {000..25} とはせずに
$(seq -f "%03g" 0 25) と書いてあること。
これはここではbashを使ってないということをアピールしているのだろうか。
それはそれとして実はwgetじゃなくてcurlを使えば簡単に連番処理できる。
% curl -O 'http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-[000-025]'
man curlすると一番最初に書いてあるから、きっとある方面では一番需要がある機能なんだろう。
すでにUbuntuでは最新のpatchがあたったバージョンのbashが使えるが、どのように修正されたのか。
いろいろ調べてみると環境変数でimportする機能は生き残っていた。
さすがに任意の名前はまずいのでBASH_FUNC_とprefixがつくようになった。
さらにsuffixとして関数らしく()もつく。
つまりxという関数だったらBASH_FUNC_x()となる。
この名前の環境変数で中身が"() { }"という形式になっていればimportされる。
% env 'BASH_FUNC_x()=() { echo hello;}' bash -c x hello
envなしでは無理。bashでもdashでもkshでもzshでも名前に()を含む環境変数は作れない。
あと例の警告もちゃんとまだ活きている。
% env 'BASH_FUNC_x()=() { :;};date' bash -c x bash: 警告: x: ignoring function definition attempt bash: `BASH_FUNC_x' の関数定義をインポート中にエラーが発生しました bash: x: コマンドが見つかりません
curlでヘッダに設定してもHTTP_がつくしhttpdによっては()が_に変換されたりするのでやはり無理っぽい。
% curl -sH 'BASH_FUNC_x(): () { :;}; date' http://localhost/cgi-bin/env.cgi | grep BASH_FUNC HTTP_BASH_FUNC_X__=() { :;}; date
気象庁|過去の気象データ検索から知りたい地点やらもろもろ選ぶ。
dayは01のように0をつけても受け付けてくれるようだ。
awkならFSとRSを適当に設定すれば結構簡単に抜き出せる。
for i in {01..28};do curl -s "http://www.data.jma.go.jp/obd/stats/etrn/view/10min_a1.php?prec_no=43&block_no=0363&year=2014&month=9&day=$i&view=" | \ awk '/data_0_0/{print date, $1, $3}' date=2014-09-$i FS='</td><td[^>]*>' RS='nowrap">|</td></tr>\n' done | tee saitamashi-201409.log
これを例のあれで日ごとの最低気温を出すとこうなる。
% sort -k1,1 -k3,3n saitamashi-201409.log | awk '!a[$1]++' 2014-09-01 18:20 20.0 2014-09-02 05:00 18.6 2014-09-03 05:40 21.2 2014-09-04 05:00 21.5 2014-09-05 05:20 21.5 2014-09-06 21:30 23.0 2014-09-07 08:50 18.4 2014-09-08 05:00 17.0 2014-09-09 05:00 18.9 2014-09-10 06:00 20.0 2014-09-11 23:40 18.3 2014-09-12 06:00 17.0 2014-09-13 04:50 17.2 2014-09-14 05:10 17.3 2014-09-15 02:10 18.9 2014-09-16 06:00 19.3 2014-09-17 23:50 20.0 2014-09-18 23:30 17.7 2014-09-19 04:30 13.4 2014-09-20 24:00 14.4 2014-09-21 05:40 11.8 2014-09-22 04:00 16.4 2014-09-23 04:20 14.1 2014-09-24 05:50 15.2 2014-09-25 03:40 21.0 2014-09-26 23:40 19.3 2014-09-27 05:50 15.7 2014-09-28 02:50 14.2
実際の値とはちょっと違うが、10分よりももっと細かい間隔でも測定してると思われる。
AWKのトリッキーな配列&連想配列の仕組み・動作と目からウロコのテクニック (1/2):CodeZineで、
このlength関数は少し特殊で、引数がない場合には$0の文字数を返し、引数が変数の場合には変数の長さを返します。 引数が配列である場合には、配列の個数を返します。 このようにlength関数はちょっとトリッキーな関数です。 一部のAWKではバグが残っていて、うまく動作しないこともあります。
のように書かれているが、これはバグではなくて一部のawkの拡張機能。
もともとlengthは文字列しか受け付けない。
POSIXでもlength(配列)は規定されていない。
そのあたりの違いは AwkChannelWiki: Awk Feature Comparisonが詳しい。
% gawk 'BEGIN{split("foo bar", a);print length(a)}' 2 % bwk 'BEGIN{split("foo bar", a);print length(a)}' 2 % gawk --posix 'BEGIN{split("foo bar", a);print length(a)}' gawk: コマンドライン:1: 致命的: length: 配列引数を受け取りました % mawk 'BEGIN{split("foo bar", a);print length(a)}' mawk: line 1: illegal reference to array a % busybox awk 'BEGIN{split("foo bar", a);print length(a)}' 0