Just another Ruby porter,

〜2015年5月上旬〜


<Older(,) | Newer(.)> | Recent(/)>> | RDF

2015-05-01 (Fri)

Amazon::SimpleDB::ClientがRecursive dependencyでインストールできない

まあ、そういうわけでamazon-simpledb-cliがインストールできなくて、
他の方法を探していたというのが昨日の真相。

% cpan Amazon::SimpleDB::Client
Reading '/home/eban/.cpan/Metadata'
  Database was generated on Sat, 02 May 2015 01:29:02 GMT
Running install for module 'Amazon::SimpleDB::Client'
Fetching with LWP:
http://www.cpan.org/authors/id/D/DT/DTRISCHUK/Coro-Amazon-SimpleDB-0.04.tar.gz
Fetching with LWP:
http://www.cpan.org/authors/id/D/DT/DTRISCHUK/CHECKSUMS
Checksum for /home/eban/.cpan/sources/authors/id/D/DT/DTRISCHUK/Coro-Amazon-SimpleDB-0.04.tar.gz ok
'YAML' not installed, will not store persistent state
Configuring D/DT/DTRISCHUK/Coro-Amazon-SimpleDB-0.04.tar.gz with Makefile.PL
Checking if your kit is complete...
Looks good
Warning: prerequisite Amazon::SimpleDB::Client 0 not found.
Warning: prerequisite AnyEvent 0 not found.
Warning: prerequisite AnyEvent::HTTP 0 not found.
Warning: prerequisite Coro 0 not found.
Warning: prerequisite Coro::AnyEvent 0 not found.
Warning: prerequisite EV 0 not found.
Warning: prerequisite Moose 0 not found.
Generating a Unix-style Makefile
Writing Makefile for Coro::Amazon::SimpleDB
Writing MYMETA.yml and MYMETA.json
  DTRISCHUK/Coro-Amazon-SimpleDB-0.04.tar.gz
  /usr/bin/perl Makefile.PL INSTALLDIRS=site -- OK
Running make for D/DT/DTRISCHUK/Coro-Amazon-SimpleDB-0.04.tar.gz
----  Unsatisfied dependencies detected during  ----
---- DTRISCHUK/Coro-Amazon-SimpleDB-0.04.tar.gz ----
    Coro::AnyEvent [requires]
    EV [requires]
    Moose [requires]
    Amazon::SimpleDB::Client [requires]
    AnyEvent::HTTP [requires]
    Coro [requires]
    AnyEvent [requires]

Recursive dependency detected:
    Amazon::SimpleDB::Client (have: N/A; want: 0.04)
 => DTRISCHUK/Coro-Amazon-SimpleDB-0.04.tar.gz
 => Amazon::SimpleDB::Client (have: N/A; requires: 0).
Cannot resolve.
  DTRISCHUK/Coro-Amazon-SimpleDB-0.04.tar.gz
  [depend] -- NOT OK

Amazon::SimpleDB::ClientとCoro::Amazon::SimpleDBが互いに依存してしまっている。


2015-05-02 (Sat)

入力ファイルへのリダイレクト問題 #シェル芸

cat file > file こんなやつ。
リダイレクトはシェルが面倒見てるのでコマンドが実行される前に処理される。
だから> fileで空になりそれを読んでも後の祭りになる。
cat file | cmd1 | cmd2 > fileとした場合はバッファ次第でうまくいくこともあるが、
結局のところ> fileが元凶なのでこれをなくさないといけない。
解決方法を少々。まずは全部読んでから書き込む。
sort -o fileとかsponge fileとかawk 'END{printf "%s", $0 > "file"}' RS='\0'とか。
dd bs=1G of=fileでもいけそうだが、結構早いタイミングでtruncateされるので残念ながら使えない。

あとはinplace modeを備えているperl, ruby, sedとか最近のgawkとか。
このあたりの処理は内部的に一時ファイルへ書き込み、名前を戻している。
こんな感じだ。

% cat file > tmp; mv tmp file

これをmvせずに実現する方法がある。
stackoverflowあたりで見た記憶があるが、一目ではちょっと理解しがたい。
見た目rmが最初に出てくるので。

% (rm file; cat > file) < file

これは最後の< fileが一番先に評価されてfd0が切り替わる。
rm fileしてもopenしたままなのでfile自体は活きている。
この状態でcat > fileすると違うi-nodeのfileに書かれるので、
元のfileが上書きされることはない。
ということは< fileと> fileのfileは別物として扱われる。
つまりやってることは一時ファイル作ってmvするのと大して変わらない。
でもぶつからない一時ファイル名を考えないといけないとか面倒なので、
そこそこ需要がある。


2015-05-03 (Sun)

4月のspam

2400通ほど。ruby-talk MLへのspam bombが効いた。

ShellCheck

話題のShellCheck。Ubuntuもパッケージがあるのでインストールは楽だ。

ShellCheck is a static analysis and linting tool for sh/bash scripts.

ということでいろいろチェックしてくれる。
先日の100本ノックの09をかけてみるとこんな感じだ。

% shellcheck 09.sh      

In 09.sh line 6:
    echo "${BASH_REMATCH[1]}"`echo ${BASH_REMATCH[2]} | grep -o . | shuf | paste -sd ""`"${BASH_REMATCH[3]}"
                             ^-- SC2046: Quote this to prevent word splitting.
                             ^-- SC2006: Use $(..) instead of deprecated `..`
                                   ^-- SC2086: Double quote to prevent globbing and word splitting.


In 09.sh line 8:
    echo $s
         ^-- SC2086: Double quote to prevent globbing and word splitting.

実際は色がつく。カラムまで表示してくれるのでわかりやすい。
-f gccとすればエディタが認識してくれる形式になる。

% shellcheck -f gcc 09.sh
09.sh:6:30: warning: Quote this to prevent word splitting. [SC2046]
09.sh:6:30: note: Use $(..) instead of deprecated `..` [SC2006]
09.sh:6:36: note: Double quote to prevent globbing and word splitting. [SC2086]
09.sh:8:10: note: Double quote to prevent globbing and word splitting. [SC2086]

VimならSyntasticが入っていれば勝手に使われる。


2015-05-04 (Mon)

TOIlet

TOIlet prints text using large characters made of smaller charactersということらしいが、
なんでこんな名前をつけたのか?
FIGletとletしか合ってないじゃないか。
まあ、それはいいとして、色がついたりひらがなやカタカナが使えるあたりがうれしい。
漢字が使えれば完璧だが。

% toilet -F crop あいうえお
  m                            "mm           m             m      
mmm#m""      m                 mmmm           ""           # m m  
  #mm#m       #    ""m       ""    #       "mm""#        ""#"   "#
 m# m" "m     #  m    #            #          m"           #m"""m 
# "m"   #     "m#    "#           #         m""m        m#"#  m  #
"m"  mm"        "               m"        m"   "mmm       "#   "" 

フィルターにはhtmlもある。

% toilet -F crop --metal --html あいうえお | sed '/<div/,$!d;s,</body></html>\|<br />,,g;s/^/HTML /' > aioeo.txt
  m                            "mm           m             m       mmm#m""      m                 mmmm           ""           # m m     #mm#m       #    ""m       ""    #       "mm""#        ""#"   "#  m# m" "m     #  m    #            #          m"           #m"""m  # "m"   #     "m#    "#           #         m""m        m#"#  m  # "m"  mm"        "               m"        m"   "mmm       "#   "" 

HTMLはちょっと力技だな。


2015-05-05 (Tue)

-iの内部処理

先日の-iの挙動をperlで確認してしてみたら、一時ファイルは作ってなかった。
というかrmするほうとまったく同じ方法だった。

% seq 10 > file
% strace -e trace=open,read,write,unlink,rename perl -i -pe 's/0/o/g' file
<前略>
open("file", O_RDONLY)               = 3
unlink("file")                       = 0
open("file", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
read(3, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", 8192) = 21
read(3, "", 8192)                       = 0
write(4, "1\n2\n3\n4\n5\n6\n7\n8\n9\n1o\n", 21) = 21
+++ exited with 0 +++

まさにopenしてからunlinkしている。-i~にするとunlinkの代わりにrenameになる。

% seq 10 > file
% strace -e trace=open,read,write,unlink,rename perl -i~ -pe 's/0/o/g' file
<前略>
open("file", O_RDONLY)               = 3
rename("file", "file~")           = 0
open("file", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
read(3, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", 8192) = 21
read(3, "", 8192)                       = 0
write(4, "1\n2\n3\n4\n5\n6\n7\n8\n9\n1o\n", 21) = 21
+++ exited with 0 +++

それしても-pでも行ごとに書き込まないのは意外だ。

unlinkする方法はrubyも同じ。というのもここら辺はperlの処理をまねているから。
Windowsではopenしたままのファイルを削除できないので、
必ずバックアップを残す-i~のような指定を強制される。

% strace -e trace=open,read,write,unlink,rename ruby -i -pe 'gsub(/0/,"o")' file
<前略>
open("file", O_RDONLY|O_CLOEXEC)        = 7
unlink("file")                          = 0
open("file", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 8
read(7, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", 8192) = 21
write(8, "1\n", 2)                      = 2
write(8, "2\n", 2)                      = 2
write(8, "3\n", 2)                      = 2
write(8, "4\n", 2)                      = 2
write(8, "5\n", 2)                      = 2
write(8, "6\n", 2)                      = 2
write(8, "7\n", 2)                      = 2
write(8, "8\n", 2)                      = 2
write(8, "9\n", 2)                      = 2
write(8, "1o\n", 3)                     = 3
read(7, "", 8192)                       = 0
write(4, "!", 1)                        = 1
+++ exited with 0 +++

-i~もperlと同じでunlinkがrenameになるだけ。

一方sedは一時ファイルを使う。

% seq 10 > file                                                                     
% strace -e trace=open,read,write,unlink,rename sed -i 's/0/o/g' file
<前略>
open("file", O_RDONLY)                  = 3
open("./sedHzMdIJ", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
read(3, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", 4096) = 21
write(4, "1\n", 2)                      = 2
write(4, "2\n", 2)                      = 2
write(4, "3\n", 2)                      = 2
write(4, "4\n", 2)                      = 2
write(4, "5\n", 2)                      = 2
write(4, "6\n", 2)                      = 2
write(4, "7\n", 2)                      = 2
write(4, "8\n", 2)                      = 2
write(4, "9\n", 2)                      = 2
write(4, "1o\n", 3)                     = 3
read(3, "", 4096)                       = 0
rename("./sedHzMdIJ", "file")           = 0
+++ exited with 0 +++

これならopenしたまま削除にはならないのでWindowsでも-iは有効なはず。
それにしてもカレントディレクトリに作るのはちょっと意外。

gawkも一時ファイルを使う。

% seq 10 > file                                                                     
% strace -e trace=open,read,write,unlink,rename gawk -i inplace '{gsub(/0/,"o")}1' file
<前略>
open("file", O_RDONLY)                  = 3
open("file.gawk.BPv947", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
read(3, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", 21) = 21
write(1, "1\n", 2)                      = 2
write(1, "2\n", 2)                      = 2
write(1, "3\n", 2)                      = 2
write(1, "4\n", 2)                      = 2
write(1, "5\n", 2)                      = 2
write(1, "6\n", 2)                      = 2
write(1, "7\n", 2)                      = 2
write(1, "8\n", 2)                      = 2
write(1, "9\n", 2)                      = 2
write(1, "1o\n", 3)                     = 3
read(3, "", 21)                         = 0
rename("file.gawk.BPv947", "file")      = 0
+++ exited with 0 +++

これもカレントディレクトリか。
まあ、どちらもGNUだけにそのあたりは同じなのかも。


2015-05-06 (Wed)

同じ文字の繰り返し #シェル芸

\bで戻すんじゃあまり役に立たないが、
コメントにあるようにprintfでつなげればいいわけだ。

$ printf %s $_{1..3}+; echo
+++

なかなか素晴しい。数字はどこに消えたかというと変数名の一部になっている。
$_{1..3}+は$_1+ $_2+ $_3+と展開されるが、_1 _2 _3という変数は存在しないので空と同じ。
よって+だけ残る。printfのformatは引数のほうが多い場合は再利用される。

$ printf %s $_1+ $_2+ $_3+; echo
$ printf %s + + +; echo
$ printf %s%s%s + + +; echo

こんな感じになる。とういうわけで_1等が存在してる破綻するのでちょっと具合が悪い。
さらにzshの場合はbrace展開よりも$_のほうが先に評価されるのでさらに都合が悪い。

% date
Thu May  7 00:55:09 JST 2015
% printf %s $_{1..3}+; echo
date1+date2+date3+

そこで発想ちょっと変えて+を前に持ってくる。で、formatで1文字だけ表示するようにする。

% printf %.1s +{1..3}; echo 
+++

こうすればbashでもzshでもokだ。

ここまでくれば3を変数にしたいところだが、なかなかうまくいかない。
zshならokだがbashだとevalしないといけない。

% zsh -c 'n=5; printf %.1s +{1..$n}; echo' 
+++++
% bash -c 'n=5; printf %.1s +{1..$n}; echo'
+
% bash -c 'n=5; eval printf %.1s +{1..$n}; echo'
+++++

brace展開されないので+{1..5}がprintfに渡っている。
eval使うぐらいならseqのほうがいいかもしれない。

% bash -c 'n=5; printf %.1s `seq -f +%g $n`; echo'
+++++

2015-05-07 (Thu)

GAWKのIndirect function call

そういえばあったなと確認する。@変数名()みたいな感じで呼び出せる。

% echo foo | gawk 'func foo(){print "foo!"}func bar(){print "bar!"}{@$0()}'
gawk: コマンドライン:1: func foo(){print "foo!"}func bar(){print "bar!"}{@$0()}
gawk: コマンドライン:1:                                                   ^ syntax error
gawk: コマンドライン:1: func foo(){print "foo!"}func bar(){print "bar!"}{@$0()}
gawk: コマンドライン:1:                                                      ^ syntax error
gawk: コマンドライン:1: func foo(){print "foo!"}func bar(){print "bar!"}{@$0()}
gawk: コマンドライン:1:                                                       ^ syntax error
% echo foo | gawk 'func foo(){print "foo!"}func bar(){print "bar!"}{@($0)()}'
gawk: コマンドライン:1: func foo(){print "foo!"}func bar(){print "bar!"}{@($0)()}
gawk: コマンドライン:1:                                                   ^ syntax error
gawk: コマンドライン:1: func foo(){print "foo!"}func bar(){print "bar!"}{@($0)()}
gawk: コマンドライン:1:                                                        ^ syntax error
gawk: コマンドライン:1: func foo(){print "foo!"}func bar(){print "bar!"}{@($0)()}
gawk: コマンドライン:1:                                                         ^ syntax error

いきなり怒られた。組み込み変数はだめか。

% echo foo | gawk 'func foo(){print "foo!"}func bar(){print "bar!"}{f=$0;@f()}'
foo!
% echo bar | gawk 'func foo(){print "foo!"}func bar(){print "bar!"}{f=$0;@f()}'
bar!

動いた。存在しないもの呼ぶとどうなるか?

% echo hoge | gawk 'func foo(){print "foo!"}func bar(){print "bar!"}{f=$0;@f()}'
gawk: コマンドライン:1: (FILENAME=- FNR=1) 致命的エラー: 内部エラー: セグメンテーション違反

SEGVとは穏やかでないが、4.1.2では直ってるようだ。

% echo hoge | ~/local/bin/gawk-4.1.2 'func foo(){print "foo!"}func bar(){print "bar!"}{f=$0;@f()}'
gawk-4.1.2: コマンドライン:1: (FILENAME=- FNR=1) 致命的: `hoge' is not a function, so it cannot be called indirectly

2015-05-08 (Fri)

w3mでぐぐると無限refreshになり使いものにならない

他にもそんなことになってる人がいるかとw3m gooogle refreshをchromeでぐぐったら出てきた。
BUG: Search result HTML includes META REFRESH, causes looping until banned
しかし、botのような人が対応してて埒が開かないようで。
Refresh(0 sec)がunusual trafficの原因なのに、
unusual trafficだからだと答えられてもねえ。
一度CAPTCHAが表示されると連続で出てきてうっとうしい。
しかもIPアドレスでbanされるようで、他のブラウザでも出てくる。

面倒なのでオプションでmeta refreshを切った。なくても困らないし。


2015-05-09 (Sat)

ピタゴラ暗号棒 #シェル芸

秘密のやりとりいたします。

どおいうときぶうたつさいえん んと

暗号棒に巻き付けるので、文字を何個か飛びに拾ってけばいい。
スパルタで使われたスキュタレー暗号だ。
ならgrep -o .してxargs -nでいけそう。

% grep -o . pitagora.txt | xargs -n2
ど お
い う
と き
ぶ う
た つ
さ い
え ん
  ん
と
% grep -o . pitagora.txt | xargs -n3
ど お い
う と き
ぶ う た
つ さ い
え ん  
ん と

おお、いけた。横書きにしよう。

% grep -o . pitagora.txt | xargs -n3 | awk '{a=a$1;b=b$2;c=c$3}END{print a"\n"b"\n"c}'   
どうぶつえん
おとうさんと
いきたい 

というわけで解けました。実際は

おとうさんと
どうぶつえん
いきたい 

だったが、気にしない。


2015-05-10 (Sun)

awkでuniq -d

重複してる行だけを抜き出すにはuniq -dを使う。

% (seq 10; seq 5 8) | sort | uniq -d
5
6
7
8

でかいデータのときはsortしたくないときもある。
そこでawkだ。

% (seq 10; seq 5 8) | awk '++a[$0] == 2'    
5
6
7
8

a[$0]++ == 1でもいいが、2個以上の2が表に出てきたはほうがわかりやすい。
2回目に出てきた順番に表示される。

% (seq 10; seq 5 8 | tac) | awk '++a[$0] == 2'
8
7
6
5

<Older(,) | Newer(.)> | Recent(/)>> | RDF


WWW を検索 jarp.does.notwork.org を検索

わたなべひろふみ
Key fingerprint = C456 1350 085F A320 C6C8 8A36 0F15 9B2E EB12 3885
Valid HTML 4.01!