ttt

getttyent

メタキャラクタのエスケープ処理が、けっこうやっかい

2009-04-13 23:43:46 | デジタル・インターネット

いまごろになって、メタキャラクタのエスケープ処理を、自分はきちんと理解できてないなぁ、と思うことがあります。

メタキャラクタというのは、

  • 「'」(シングルクォート)
  • 「"」(ダブルクォート)
  • 「\」 (バックスラッシュ、場合によっては¥マーク)
  • 「$」(ドル)

など、単なる記号文字として以外にも、何か別の意味ありげな機能を持っている文字のことです。

何か別の意味ってのは、たとえば、シェルのコマンドライン上で、「$」を使った場合、

% echo $LANG
C

というように、「$LANG」と書くと、変数LANGの値へと展開されます。

エスケープ処理というのは、たとえばこの「$」の機能を無効化することです。
ひとつの方法としては、「'」で囲んでやることで

% echo '$LANG'
$LANG

というように、「'」で全体を囲むと、「$」がそのまま出てきます。
エスケープ処理の方法は、何通りもあることがあり、たとえば「\」を使っても、同じ結果が得られます。

% echo \$LANG
$LANG

このエスケープ処理なんですが、けっこう間違えやすくて、やっかいものです(そう思ってるのは、私の技量不足とか、思慮が足りないとか、ダメダメだとか・・・)。

たとえば、「"」をエスケープしたいと思った場合、

/bin/sh の場合

$ echo "aaaa\"hoge\"bbbb"
aaaa"hoge"bbbb

なんていう風に書くことができます。
ところが、/bin/csh の場合、同じようにやっても

% echo "aaaa\"hoge\"bbbb"
Unmatched ".

と、エラー扱いされてしまいます。ツールによって、メタキャラクタの働き方が微妙に違うんですよね。この、「ツールによって解釈が違う」ってのが、ものすごくやっかいだと思います。

「'」(シングルクォート)は、たいてい、かなり強力にエスケープしてくれるんですが、「'」で囲まれた中に「'」を書けないんですよね。

/bin/sh の場合

$ echo 'aaaa\'hoge\'bbbb'
>  ・・・まだコマンド文字列の続きだと思われてしまっている。

/bin/csh の場合

% echo 'aaaa\'hoge\'bbbb'
Unmatched '.

「'」をそのまま出したいだけなら、たとえば、ダブルクォートの中に、シングルクォートを書くと、できちゃいます。

/bin/sh の場合

$ echo "aaaa'hoge'bbbb"
aaaa'hoge'bbbb

/bin/csh の場合

% echo "aaaa'hoge'bbbb"
aaaa'hoge'bbbb

なんかもう、こういうルールを何個も覚えなくちゃならないかと思うと、頭が混乱してきます。

PHPで、PostgreSQLを使うスクリプトを書いているとき、SQL文を書くときに、どういうわけか、ときどき、「\\\\」と、「\」を4個も重ねて書かなくてはならないときがあって、あーもー何がなんだか と思うことがあります。

この前やった失敗は、途中で「"」が消えてなくなると思って書いてたら、意に反して、最後まで「"」が生き残って、その結果、データベースに、「"Hello world"」のように、「"」がついたまま、文字列が登録されてた、とか 

ある文字集合を使っているときに、エスケープ文字も同じ文字集合に含まれているために、こういうやっかいなことになるわけだから、もしもエスケープ文字が、別の文字集合から持ってこれたらいい、でも別の文字集合を使うときは、また別の別の文字集合からエスケープ文字を持ってきて、・・・あーもー何が何だか


コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。