どさにっきクラウド 〜2009年4月上旬〜

by やまや
<< = >>

2009年4月2日(木)

ダマされないぞ

_ openssl

01-Apr-2009: Beta 1 of OpenSSL 1.0.0 is now available, please test it now
エイプリルフールにきまってる。0.9.x のままあと10年戦ってください。


2009年4月6日(月)

#!sed

_ Linux 上で #!/usr/bin/sed -f なスクリプトを書いた。実行。

-bash: ./hoge.sed: /usr/bin/sed: bad interpreter: No such file or directory
は? なんぞ?

_ 今までぜんぜん気づいてなかったが、Linux の世界では sed は /usr/bin じゃなくて /bin らしい。キモい。キモすぎる。

_ こういうパスの違いを吸収するには env を使うんだ!とばかりに

#!/usr/bin/env sed -f
とすると、動きません。 理由。shebang 行の環境依存性を排するなんて幻想でしかないんだ。

echo の罠

_ きょう新人くんがハマってた。って、もう今月からは2年目くんか。

_ 実行結果として以下のような複数行の応答を返すコマンドがある。

hoge fuga piyo moga
abcdefg
1234567890
AAAAAA
zzzz
で、このコマンドをこんなふうに sh スクリプトから呼び出す。
result=`なんかコマンド`
echo $result

_ 彼はコマンドの実行結果とまったく同じものが出力されると期待してたんだけど、現実は無惨。

 zzzzAA7890iyo moga
こんなわけわからんものが出てきて、なんでーと泣きついてきた。

_ 彼の教育を考えるのであれば適当にヒントだけ与えて自分で理由と解決策にたどりつけるようにしてやれればよかったんだろうけど、夕方近くにもなってまだ昼飯も食う時間も取れてないようなときに「やっぱダメです」「そりゃここがおかしい」なんてやりとりを何度もやってられんので、なぜこうなったのか、どこを修正すればいいのかをさっさと説明して終わらせてしまった。

_ ちうことで、ここではヒントだけ書いておくので、何がおかしくてこんなことが起きちゃったのかは自分で考えてね。ちゃんとした答はそのうち書く。「echo は引数をそのまま出力するコマンドじゃなくて引数リストを空白で連結したものを出力するコマンドだよ」


2009年4月9日(木)

echo の罠・つづき

_ このまえの件の解答編。

_ 罠はふたつある。片方は罠というより単に無知なだけといった方がいいかもだけど。

_ 前者。変数の中身に改行コードはちゃんと残っているが、シェルにとっては改行もスペースと同じように引数の区切り文字のひとつでしかない。で、echo は引数をそのまま出力するコマンドではなく、引数リストを空白で連結して出力するコマンドであるから、結果として変数に含まれる改行(LF)が空白に変換されることになる。

_ 後者。CR はカーソルを行頭に戻す。LF は1行送る。DOS/Windows では CR+LF で改行を表現するけど、UNIX では LF だけで改行を実現する。CR が特別な意味をもたない UNIX で動く sh にとって、LF は区切り文字だけど CR は区切り文字ではないが、端末にとっては行頭に戻すという CR の制御コードは有効。

_ つーわけで、変数が展開された後、echo でほんとのほんとに出力される文字列はこうなる。

hoge fuga piyo moga<CR> abcdefg<CR> 1234567890<CR> AAAAAA<CR> zzzz<CR>
このとおりちゃんと出力されるが、LF のない CR のせいで何度も行頭に戻って画面上の同じ場所に文字を上書き表示するため、最終的に画面に残るのは
 zzzzAA7890iyo moga
という謎文字列になる。端末に直接表示させず、CR の機能を無視するツール(less とか od とか)に出力を食わせてみれば、ほんとの出力を確認できる。

_ で、この困った現象をやめさせるにはどうすればいいか。よーするに $result という1個の変数がシェルに展開されて複数の引数として echo に渡されてしまってるのが元凶なわけなので、これを1個の引数のまま echo に渡せばよい。つまり、

echo "$result"
とする。だからあれほどシェルの変数はダブルクォートで括れといったのに。括らず生のまま使ってわざとシェルに分解させて使うこともあるけど、どっちかというと高等テクニックなので、シェルの引数展開のしくみをちゃんと理解するまではとりあえずダブルクォートで括っとけ。

_ なお、"$result" としても CR がまだ残ったままなので、場合によっては CR を除去しておいた方がいいかもしれない。つまり、

result=`なんかコマンド | tr -d \\r`
とする。echo するときに除去してもいいけど、たいていの場合は先に CR を除去しておいた値を変数につっこんでおいた方がしあわせ。

_ で、その2年目くんに「ダブルクォートの方はともかく、CR のことなんて man に書いてないですよねぇ。そういうのどこで知るんですか」と聞かれた。うーん。どこと言われても。あちこちで、としか言えんぞ。


<< = >>
やまや