1. ホーム
  2. string

[解決済み] X""で空の文字列をテストする 重複] [重複

2023-08-19 18:50:56

質問

Bashで空文字列をテストできることは知っています。 -z のようにします。

if [[ -z $myvar ]]; then do_stuff; fi

のように書かれているコードをよく見かけますが、これはどうなんでしょうか?

if [[ X"" = X"$myvar" ]]; then do_stuff; fi

その方法はより移植性が高いのでしょうか?の時代以前からの歴史的な屑なのでしょうか? -z ? それは POSIX シェル用なのでしょうか (私はこの方法が bash )? 私の歴史/移植性のレッスンのための準備。


同じ質問が、Server Fault で bash変数が空であるかどうかを決定する方法は? という質問がありましたが、誰も なぜ を含むコードが表示されます。 X"" のようなものがあります。

どのように解決するのですか?

根本的に、今はもうずっと過去の時代なので、動作が test の動作はより複雑で、異なるシステム間で一様に定義されていませんでした (そのため、移植可能なコードは移植不可能な構造を避けるために注意深く書かなければなりませんでした)。

特に、以前は test がシェル組み込みになる前は、別の実行ファイルでした (なお、MacOS X では今でも /bin/test/bin/[ を実行ファイルとして使用)。 そんな時、書き込み。

if [ -z $variable ]

いつ $variable が空だった場合、テストプログラムはそのエイリアスである [ を3つの引数で呼び出します。

argv[0] = "["
argv[1] = "-z"
argv[2] = "]"

というのは、変数が空なので、展開するものがなかったからです。 つまり、安全なコードの書き方としては

if [ -z "$variable" ]

これは確実に動作し、4つの引数を test 実行ファイルに 4 つの引数を渡すことで確実に動作します。 確かに、テスト プログラムは何十年もの間、ほとんどのシェルに組み込まれていますが、古い装置はなかなか壊れませんし、さらに昔に学んだ良い習慣も変わりません。

X 接頭辞によって解決された他の問題は、変数に先頭のダッシュが含まれていたり、等号や他の比較演算子が含まれていたりする場合に何が起こるかということでした。 (あまり良くない例ですが) を考えてみましょう。

x="-z"
if [ $x -eq 0 ]

これは、迷子の(誤った)引数による空文字列のテストでしょうか、それとも数字でない最初の引数による数字の等値性テストでしょうか? 1990年頃、POSIXが動作を標準化するまでは、システムによって異なる答えが用意されていました。 そこで、これに対処する安全な方法として

if [ "X$x" = "X0" ]

または(私の経験では、それほど普通ではありませんが、完全に同等です)。

if [ X"$x" = X"0" ]

テストが別の実行ファイルである可能性と結びついた、このようなすべてのエッジケースは、移植可能なシェルコードが、現代のシェルが実際に必要とするよりも大量にダブルクォートをまだ使用しており、X-プレフィックス表記は、誤解されることがないようにするために使用されていたことを意味するものでした。