TIM Labs

2011年9月アーカイブ

問題

シェル(ただし Bourne Shell 系に限る)はお友達です。 一見すると役に立たないように思えるコマンドでも、 組み合わせ次第で複雑な処理をこなすための道具になります。

例えば行毎に ID が記載されているファイル ids があったとしましょう。 各 ID を SHA1 ハッシュ値に置き換えたものが必要な場合、 以下のコマンドで生成することができます (SHA1 ハッシュ値の算出には shasum を使っています):

cat ids | while read id
do
    echo -n "$id" | shasum
done | cut -d ' ' -f 1 >ids.sha1

このように、行単位で何か処理を行う場合には read を使います。 ちょっとしたことなら sedawk で済ませられるのですが、 上記のように「行毎にコマンドを実行して云々」をやろうとすると無理が出てくるので、 read を使う方が自然です (若者ならば何であれ perl で済ませるところですが、 今回は read を使いたいので考えないことにします)。

ところで、いきなり上記のようなコマンド列がすらすら書ける人は稀です。 ふつうの人は単純な処理(例えば指定した ID から SHA1 ハッシュ値を生成するだけ)を実現してから、 徐々に目的の処理を実装していくことになります。

筆者の場合、 read は滅多に使ったことがないため、 まずおさらいがてら read の使い方の確認から始めました。 read は標準入力から1行読み込み、 読み込んだ文字列を引数で指定された名前の変数に格納します (話を単純にするため「単語」分割云々は考えないことにします)。 ということは、以下のコマンドを実行すると i には 2 が格納されるので、 1 2 の順で出力が行われるはずです。試してみましょう:

$ i='1'; echo "$i"; echo '2' | read i; echo "$i"
1
1

えっ......

3回目の echo では 2 が出力されると予想したのですが、 何故か 1 が出力されました。一体 read が格納した文字列はどこへ消えたのでしょうか。

さらに不可思議なことに、以下のように while で括ると今度は期待通りの出力がなされます:

$ i='1'; echo "$i"; echo '2' | while read i; do echo "$i"; done
1
2

まさかと思って while の後に i の内容を出力してみると、今度は以下の結果になります:

$ i='1'; echo "$i"; echo '2' | while read i; do echo "$i"; done; echo "$i"
1
2
1

read の挙動を考えると、 while の有無(と前後)で i 内容がころころ変動するのは不可思議です。 これはどういうことなのでしょうか。

問題

VimとExcelを組み合わせて全く新しいSQLクエリーを生成する でも述べたように、諸事情で Excel を使う機会はよくあるのですが、 その時に困るのが文字列処理です。

Excel は組み込みで CLEANTRIMUPPERPHONETIC などの豊富な関数が用意されているものの、 何故か正規表現を使った文字列比較や文字列置換は標準で関数が用意されていません。 単純な処理ならば組み込み関数を組み合わせてどうにかできるものの、 「s/,+/,/gs/,$// ができたらなぁ......」 と思うことはしばしばあります。

どうにかして Excel の数式で正規表現を使うことはできないでしょうか。

問題

Mercurial 独特の概念として、マルチプルヘッドというものがあります。

@  2:d9ae2b51cade | head b
|  default
|
| o  1:8141de67f6ee | head a
|/   default
|
o  0:6af850d9f57f | initial commit
   default
図1. defaultブランチがマルチプルヘッド(先端(HEAD)が複数存在している状態)

マルチプルヘッドは hg merge でマージして一つのヘッドに統合してからpushするのがマナーですが、push -fで強制的にpushすることができてしまいます。

[troter:~/tmp/multiple-head]
% hg push
pushing to /home/troter/tmp/central
searching for changes
abort: push creates new remote head 8141de67f6ee!
(did you forget to merge? use push -f to force)
[troter:~/tmp/multiple-head]
% hg push -f
pushing to /home/troter/tmp/central
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 2 files (+1 heads)
[troter:~/tmp/multiple-head]
%

何とか禁止することはできないでしょうか。。。

問題

ある程度 Vim を常用していると、それなりの頻度で以下のような問題に遭遇します:

  • HEAD を追いかけていたら手ひどいミスに遭遇した。少し昔のパッチレベルにまで巻き戻したい。
  • 最近のバージョンに更新したらプラグインの動作が変わった。どのパッチレベルで問題が起きたか調べたい。
  • そもそも最近のバージョンに更新するのが何だか面倒。
  • 複数のバージョンを並行して利用できるようにしたい。

しかしこのようなことを手動で管理するのは面倒です。 どうにかしてこのような作業を簡単に行えないものでしょうか。

このアーカイブについて

このページには、2011年9月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2011年8月です。

次のアーカイブは2011年10月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。