いちおう技術系ネタ帳ということで、日記はあまり書かない。
2012-01-22
xargsメモ
xargsはよくfindと組み合わせて一括処理したりするのに使うけど、失敗すると大ダメージを受けるのでお勉強。
プログラムを指定しないとecho
xargsにプログラムを指定しないとechoが使われるのでどんな感じに渡されるのか確認できる。
$ ls -l total 0 -rw-r--r-- 1 pasela staff 0B 1 22 17:11 foo -rw-r--r-- 1 pasela staff 0B 1 22 17:11 bar -rw-r--r-- 1 pasela staff 0B 1 22 17:11 baz $ ls | xargs foo bar baz
NUL(\0)区切りで受ける
xargsはデフォルトではホワイトスペースで区切るので、たとえば"Foo Bar"というような空白を含むファイルがあるときに普通に実行すると残念なことになる。
$ ls -l total 0 -rw-r--r-- 1 pasela staff 0B 1 22 17:11 Foo Bar -rw-r--r-- 1 pasela staff 0B 1 22 17:11 baz $ find . type -f -print | xargs rm rm: ./Foo: No such file or directory rm: Bar: No such file or directory
これはこんな感じの3引数として渡される。
rm "./Foo" "Bar" "baz"
これを避けるにはリストを\0区切りで出力して、受ける方も\0区切りで受けるとよい。
findのほうは-print0を使うと\0区切りで出力してくれ、xargsは-0で入力を\0区切りとして受け取れる。
$ find . type -f -print0 | xargs -0 rm
これはこんな感じの2引数として渡される。
rm "./Foo Bar" "baz"
ちなみにGNU版の場合は-d delimで他にも任意のデリミタを指定することができる。
実行コマンドを表示する
-tを指定すると実行するコマンドを表示してくれる。
$ ls | xargs -t /bin/echo bar baz foo bar baz foo
表示した上で実行もするので、dry run的な確認には使えない。勘違いしないように。
ログとして残したい場合なんかにいいかも?
実行するかどうか確認する
-pを指定するとコマンド実行毎に実行するかどうか確認してくる。yで実行、それ以外でスキップ。
$ ls | xargs -p /bin/echo bar baz foo?...y bar baz foo
入力n行ごとに実行する
-L 数字で指定行数ごとにコマンドを実行させられる。
$ ls | xargs -L 1 -t /bin/echo bar bar /bin/echo baz baz /bin/echo foo foo $ ls | xargs -L 2 -t /bin/echo bar baz bar baz /bin/echo foo foo
引数n個ごとに実行する
-n 数字で指定個数の引数ごとにコマンドを実行させられる。
$ ls | xargs -n 1 -t /bin/echo bar bar /bin/echo baz baz /bin/echo foo foo $ ls | xargs -n 2 -t /bin/echo bar baz bar baz /bin/echo foo foo
ん、-Lとの違いがわからない?
ではこうやって1行の入力にしてみると違いがわかるはず。
$ echo "foo bar baz" | xargs -n 1 -t /bin/echo foo foo /bin/echo bar bar /bin/echo baz baz $ echo "foo bar baz" | xargs -L 1 -t /bin/echo foo bar baz foo bar baz
-nのほうはホワイトスペースで3つに区切られた上で、1つずつ実行されている。
-Lのほうは1行の入力ずつ実行されている。
置換文字列で挿入する
普通はxargsに渡したコマンドの最後にxargsが引数を追加して実行されるが、cpやmvみたいにコマンドラインの途中の位置に挿入して欲しい場合は-I repstrが使える。
普通にやると……
$ ls | xargs -t cp /path/to/dest_dir cp /path/to/dest_dir bar baz foo usage: cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file target_file cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file ... target_directory
こんな感じのコマンドラインで実行されてしまうが、-Iを使うと……
$ ls | xargs -I % -t cp % /path/to/dest_dir cp bar /path/to/dest_dir cp baz /path/to/dest_dir cp foo /path/to/dest_dir
このように-Iで指定した文字列のところを置換して処理してくれる。
(BSDの場合)もうちょっと賢く
上記のは見てのように自動的に-L 1として処理されてしまうので効率があまりよくない。
ここはcp bar baz foo /path/to/dest_dirってなってほしいよね?
こういう場合、BSD版なら-J repstrを使うとよい。
$ ls | xargs -J % -t cp % /path/to/dest_dir cp bar baz foo /path/to/dest_dir
複数プロセスで並列に実行する
-P 数字を使うと指定したプロセス数で並列実行してくれる。デフォルトは1。
例えばこんな感じのURLリストがあったとして……
$ cat urls.txt http://www.google.co.jp/ http://www.yahoo.co.jp/ http://www.goo.ne.jp/
こんな感じで実行すると普通は1つずつ実行される。
$ cat urls.txt | xargs -n 1 -t curl >/dev/null curl http://www.google.co.jp/ % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 12352 0 12352 0 0 130k 0 --:--:-- --:--:-- --:--:-- 177k curl http://www.yahoo.co.jp/ % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 25694 0 25694 0 0 53247 0 --:--:-- --:--:-- --:--:-- 253k curl http://www.goo.ne.jp/ % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 64743 0 64743 0 0 630k 0 --:--:-- --:--:-- --:--:-- 916k
-Pを指定してやるとこれを並列に実行して一気にダウンロードできる。
$ cat urls.txt | xargs -n 1 -P 3 -t curl >/dev/null curl http://www.google.co.jp/ curl http://www.yahoo.co.jp/ curl http://www.goo.ne.jp/ % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 12340 0 12340 0 0 127k 0 --:--:-- --:--:-- --:--:-- 191k 100 64796 0 64796 0 0 590k 0 --:--:-- --:--:-- --:--:-- 832k % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 25703 0 25703 0 0 59137 0 --:--:-- --:--:-- --:--:-- 522k
2012-01-06
Webカラー名を一覧表示するunite source作ってみた
vim |
![]()
vimにもカラーピッカーみたいなプラグインはいくつかあって、自分はcolorsel.vimとかColorV.vimを使っていたんだけど、ColorVのカラーリストがなんとなく気に入らなかったので、uniteのソースとして自作してみることにした。
unite-webcolorname
https://github.com/pasela/unite-webcolorname
こんな感じで色を選択して挿入したりコピーしたりできる。
Vim script自体もあんまり書いたことないしuniteのsourceも作ったことなかったので、あちこちのsource plugin見ながらなんとか作ってみたよ。
シンタックスハイライトの例がほとんどなかったのと、ハイライトの目的がちょっと普通じゃないので試行錯誤が必要だったけど、こんな感じに綺麗にできた。
選択中の項目が白くなっちゃうのがちょっと残念だけど、まぁ仕方ないかな?
カーソル下のcandidateから色取ってCursorLineを逐一書き換えるという方法も浮かんだけどそもそもできるのかわからないし、選択中の項目がわかりにくくなりそうだからまぁいいかな、と。気が向いたらそのうちやってみるかも。
2011-12-26
Node.jsはじめてみた
話題……というには今更だけどなんとなくNode.jsを始めてみた。
本当はSymfony2をモノにしようと勉強する予定だったんだけど、飲み会で「Node.jsやりたい!」って言ってる人がいて「ふーん」と思いつつもちょっと気になって手を出してみた。そしたらなんか面白くなってきてハマっちゃったかもw
Node.jsに抱いていたイメージ
自分がNode.jsに抱いていたイメージは「サーバサイドJavaScriptの一種」「ノンブロッキングI/Oとイベントループで大量のアクセスもさばけるらしい」とかそんな程度だった。最近だと「WebSocketのために使われる」みたいなイメージも。
でもまぁ、一部の用途ではいいソリューションになるんだろうなーと思いつつも、どこか「面白そうだったのでサーバサイドでJavaScript使えるようにしてみましたー」的な遊びっぽいイメージのほうが強かった。
けど、どうもそうじゃなかったらしい。
Node.jsとは何か
Node.jsを試してみるにあたって、とりあえず情報収集していると“node.jsとは何か”という自分の疑問にずばり答えてくれそうなエントリが見つかった。(4)まであるので自分みたいに「Node.jsって結局なんなの?」って思ってる人は是非とも読むべし。
簡単にまとめるとこういうことらしい。
- C10k問題でよく比べられているアーキテクチャにスレッドモデルとイベントループモデルがある。*1
- スレッドは数が多くなるとメモリ消費量が増える。
- 対してイベントループは1プロセスのままなのでたいしてメモリ消費量は増えない。
- だけどイベントループはどこかにブロックするやつがいると全体の処理が止まってしまって大変!
- そして既存の言語にもイベントループの実装はあるけど、Non-Blocking I/Oを強制しているわけではないので止まってしまう不安がつきまとう。
- 対してJavaScriptは元々がシングルスレッドでイベントループという仕組みを持っていた。
- さらにWebやってる人ならだいたいJavaScriptは触ったことあるよね!→学習コストが低い。
- さらにGoogle V8という高性能で組み込みやすいJavaScriptエンジンがある!
こうしてNode.jsは誕生したらしい。
とりあえず環境を作ってみる
前置きがすごーーーーーく長くなったけど対象のことを知るのは大事よってことで。むしろ、どういうものかわかったことで俄然興味が湧いてきた。
さてさて、自分はMacなのでhomebrewで簡単にインストールできるみたいなんだけど、どうやらnaveとかnvmっていう環境管理ツールを使うのがいいらしい。
RubyのRVMやPerlのPerlbrew、Pythonのvirtualenvみたいなやつで、Node.jsをバージョンごとにインストールして切り替えたりできるやつ。
nave
https://github.com/isaacs/nave
- npmというNode.jsにおけるパッケージ管理システムの作者が作成しているので、なんとなく安心感がある。
- nave useするときにシェルが再実行されるのでなんとなく気持ち悪い。環境変数とかぐちゃっとしそうだし。そのうち改善されるかな?
nvm
https://github.com/creationix/nvm
- npmもインストールしてくれる。らしいけど、最近は最初からNode.jsについてる?
- nvm useしてもPATHとかをexportし直すだけでシェルを多重起動したりしない。
- zshといまいち相性が良くない。時々エラーが出たりする。が、概ね動く。
nvmのインストール
自分はnvmを入れてみたけど、たぶんどっちも大差ないと思う。
というわけでnvmのインストール。
git clone git://github.com/creationix/nvm.git ~/.nvm
source ~/.nvm/nvm.sh
んで、.bashrcとか.zshrcにもsource ~/.nvm/nvm.shを書いておく。
これで完了。
ちなみにnaveの場合はsourceで読み込む必要もなく、nave.shを落としてきてそれをコマンドとして使えばいいみたい。
使い方はこれ系のツールとだいたい同じで、サブコマンドのinstallとかuseとかを使えばよい。とりあえず実行するとヘルプが表示される。
Node.jsのインストール
nvm install v0.6.6
これだけ。で、使ってみる。
nvm use 0.6.6
これでv0.6.6が有効になった。
とりあえずHello, World!
Node.jsのトップにあるEXAMPLEを試してみよう。
var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(1337, "127.0.0.1"); console.log('Server running at http://127.0.0.1:1337/');
これをhello.jsとかに保存して
node hello.js
で実行。
ブラウザでhttp://127.0.0.1:1337/にアクセスすると「Hello World」が表示される。
シンプルなコードなのでだいたい上のコードがどういう内容なのか想像が付くはず。ちょっと肉付けしたら色々できそうでワクワクしてきたでしょ?
ライブラリとかフレームワークとか
Node.jsにはnpmという他の言語にもよくあるようなパッケージ管理システムがあって、これを使って色々なライブラリをインストールできる。
MySQLクライアントのnode-mysqlとか、WebアプリケーションフレームワークのExpressとか、テンプレートエンジンのejsとかとにかく色々ある。
npm install express
ってな感じで簡単にインストールできる。
コマンドラインツールとして
ここまで来るまで実はNode.jsってWebサーバなんだと思ってたんだけど、サーバたらしめてるのはどう見てもrequireしてるhttpってやつやnetのおかげらしくて、普通にJavaScriptを書けばサーバでもなんでもない普通の処理もできるってことに気づいた。
実際そういう使い方もあるみたいだし、標準でReadlineライブラリもあるし、npmにはoptimistとかjs-optsといったgetopt系のライブラリもあるみたい。
組み込みライブラリ、npm含めて結構色々揃ってるからそういう使い方もいいかなーとか思ったり。
っていうか本体にREPLついてるじゃん!
ドキュメント
とりあえずこの辺のドキュメントが参考になった。
特にハンズオン資料は一通り目を通すとNode.jsで何ができるのか、どうしたらいいのかがざっくりと理解できる。
で、APIマニュアルにざっと目を通してどんな機能があるのか把握しておけばよいかと。目次見るだけでも色々あってワクワクするね!
今後やりたいこと
2011-12-19
HTMLAnchorElement.hrefとElement.getAttribute("href")の違い
web, JavaScript |
![]()
JavaScriptなんかでURIの示すリソースをどうこうするときに、どうしても絶対URIが欲しいことがあるんだけど、頑張って自分で組み立てなくても、相手がA要素なら意外と簡単に取れるみたい。
<a id="bar" href="../foo/bar.html">bar</a>
こんな感じのA要素があったとして、普通にHTMLAnchorElementオブジェクトのhrefプロパティを参照すると解決済みの絶対URIが入っているらしい。
ここでElement.getAttribute()を使うと現在設定されている値そのものが取れてしまう。
var link = document.getElementById('bar'); console.log(link.href); // => http://example.com/path/to/foo/bar.html console.log(link.getAttribute('href')); // => ../foo/bar.html
仕様がいまいちわからない
ぐぐってみるとわりと常識らしいんだけど、どこまで信頼していいのか、ブラウザ互換性とかどうなのかがいまいちわからなかった。
DOM Level 2で規定されているという記述があったのでDOM Level 2 HTMLのHTMLAnchorElementのところを見てみると、
- href of type DOMString
- The absolute URI [IETF RFC 2396] of the linked resource. See the href attribute definition in HTML 4.01.
と書かれているので、この属性が絶対URIを扱うのは確かなようだ。
ただ、あまりにもそっけなく書いてあるので、相対URIを入れた場合はどうなるのか、自動的に絶対URIに変換してくれるのか、それとも設定する側が絶対URIを設定しなければいけないのか、とかいまいちよくわからない。
ちょっと試した感じだと相対URIを突っ込んでも読みだすときには絶対URIとして読み出せる模様。
「相対URIを絶対URIに変換するテクニック」のひとつとして、HTMLAnchorElementを生成してhrefプロパティから取り出すというのを時々見かけるので、きっと大概の環境で動くんだろう。うん、きっとそう。
2011-07-04
Macにpythonbrew+virtualenvでPython環境を作ってみた
Ruby、Perlときたので残るPythonについてもpythonbrewとvirtualenvで環境を整えてみた。いい加減内容がテンプレ的で飽きてきたけどw
PythonもSnow Leopardでは2.6.1なので2.7とか3.2が使いたいよねーってことで。
タイトルには「Macで〜」って入ってるけど、pythonbrew自体はUNIX系の環境で使えます。
pythonbrewっていうのは、複数のPythonバージョンを簡単にインストールしたり切り替えたりできるようにするツールで、RubyでいえばRVM、Perlでいえばperlbrewみたいなもん。*1
これを使えばOS標準の環境も汚さないし、2.6系、2.7系、3系とかプロジェクトで使用中のバージョンと最新版とか色々な複数の環境を簡単に共存させて使い分けることができる。ステキ!
pythonbrewを使うとこんな感じでサクサク環境を使い分けることができるようになる。
pythonbrew install 2.7.2 ←Python-2.7.2をインストール pythonbrew install 3.2 ←Python-3.2をインストール pythonbrew switch 2.7.2 ←Python-2.7.2に切り替え pythonbrew switch 3.2 ←Python-3.2に切り替え
virtualenvっていうのは、Pythonの新しい独立した環境を構築して自由に切り替えて使えるようにするツール。
pythonbrewと何が違うのかというと、pythonbrewはPythonのインストールから管理してくれるのに対して、virtualenvは既存の実行環境を元にして新しい仮想環境を作ってくれる点が異なる。
virtualenvと、あとそれを便利にするvirtualenvwrapperっていうのを使うとこんな感じでサクサク環境を使い分けることができるようになる。
mkvirtualenv -p /path/to/python-2.6 foo ←2.6をベースにfooという環境を作成 mkvirtualenv -p /path/to/python-2.6 foo2 ←2.6をベースにfoo2という環境を作成 mkvirtualenv -p /path/to/python-3.2 bar ←3.2をベースにbarという環境を作成 workon foo ←foo環境に切り替え workon bar ←bar環境に切り替え deactivate ←virtualenvの環境から抜けてOS標準に戻る
どっちかでいいんじゃないかって気もするけど、そう思うんならそれでいいんだと思う。
とりあえずpythonbrewで新しいインタプリタをインストールして、virtualenvで用途別にぽこぽこ環境を増やしていくというのが流行りらしい(?)のでそれに倣ってみる。
pythonbrewのインストール
pythonbrewのインストール方法は公式サイトに書いてあるコマンドを叩けば簡単に入る。
curl -kLO https://github.com/utahta/pythonbrew/raw/master/pythonbrew-install chmod +x pythonbrew-install ./pythonbrew-install
流れとしてはこんな感じ。
perlbrewと同じだね。
これで$HOME/.pythonbrewにpythonbrewの環境ができあがる。
pythonbrewに関するコマンド
pythonbrewで入れることのできるバージョン一覧
pythonbrew list -k
pythonbrewのアップデート
pythonbrew update
これでpythonbrewが最新になる。
Pythonのインストール
pythonbrew install 2.7.2
別名をつけてインストール
pythonbrew install --as=mypython 2.7.2
これでPython-2.7.2がmypythonという名前でインストールされる。
configureオプションを指定する
pythonbrew install --configure="CC=gcc_4.1" 2.7.2
pythonbrew uninstall 2.7.2
Pythonbrewを切り替える
入ってるPython一覧
pythonbrew list
これでインストールされているPythonの一覧が表示される。
Pythonを切り替える
pythonbrew switch 2.7.2
これで2.7.2を使うためのPATHとかその他の環境変数が切り替わったので、今すぐPython-2.7.2が使える状態になる。
RVMとは逆、perlbrewと同じで永続的に切り替わった状態になる。
現在のシェルだけ切り替える
pythonbrew use 2.7.2
切り替え状態はこのシェルだけ。
pythonbrew off
これでperlbrewで入れたやつじゃない環境に戻る。
複数のPythonでまとめて実行
pythonbrewにはインストールしてあるPythonでまとめて実行する機能がある。
これを利用すると書いたプログラムが他のバージョンでもちゃんと動くか一発でテストできる。
まとめて実行
pythonbrew py hello.py
pythonbrewでインストールした全Pythonで実行される。
特定のバージョンで実行
pythonbrew py -p 2.6.6 -p 2.7.2 hello.py
2.6.6と2.7.2で実行される。
リンクを張る
pythonbrew symlink
こうするとpy2.6とかpy2.7.2みたいなリンクが.pythonbrew/binに出来るので手軽に実行出来るようになる。
ただしpythonbrew offするとリンクも消えてしまうみたい。
あと、実はpythonbrewはpybrewというコマンド名でも実行できる。
virtualenvとvirtualenvwrapper
続けてvirtualenvのインストール。
とりあえずどれでもいいのでvirtualenvを入れたい環境にswitchする。
pythonbrew switch 2.7.2
pipでvirtualenvとvirtualenvwrapperをインストール。
pythonbrewによってeasy_installとpipもインストールされている。
pip virtualenv virtualenvwrapper
.bashrcとかに環境変数VIRTUALENVWRAPPER_PYTHONを設定する。
VIRTUALENVWRAPPER_PYTHON=$HOME/.pythonbrew/pythons/Python-2.7.2/bin/python
pythonbrew symlinkでできたpy2.7.2とかを指定するのがいいっぽいんだけど、pythonbrew offすると消えちゃうので直に指定してみた。
.bashrcとかでvirtualenvwrapper.shを読み込む。
source $HOME/.pythonbrew/pythons/Python-2.7.2/bin/virtualenvwrapper.sh
これもpythonbrew symlink -d 2.7.2 virtualenvwrapper.shとかでできたのを指定するっぽいんだけど(ry
virtualenvで環境を操作する
まー、冒頭のサンプルの通り。
それ以外に一覧を表示するlsvirtualenvとか、環境を削除するrmvirtualenvとか色々ある。

