bashスクリプト[x $ 1 = x]


21

私はbashスクリプトを読んでいますが、そこで何が起こっているのか理解できません。

#!/bin/sh
[ x$1 = x ] 

2行目で何が起こっているの[ x$1 = x ] ですか?

回答:


27

$1空であることがチェックされますが、引用符で囲む必要があります(と同じ[ -z "$1" ])。いくつかの非常に古いシェルは空の文字列を適切に処理しなかったため、ポータブルスクリプトの作成者はこのスタイルのチェックを採用しました。それは何十年もの間必要ではありませんでしたが、人々はまだそうするので、人々はまだそうするのです。


うん、あなたはもうこれのようにそれをしないで、よりモダンなスタイルを採用するべきではありません。PDP11で作業している場合を除きます。
MacLemon 14年

4
空の文字列ではありません。[ x$1 = x ]まだ間違っているが、[ "x$1" = x ]問題持っているシェルのためになる$1である!か、(またはを-n.... [ "" = "$1" ]case $1 in "")もOKしかしでしょう。
ステファンシャゼル14年

2
@MacLemon、さかのぼる必要はありません。[ -z "$1" ]また[ "$1" = "" ]、Solaris 10の/ bin / shでは動作せず、前者はdash-0.5.4で動作します。
ステファンシャゼル14年

1
最後の文に余分な+1!
グレンジャックマン14年

1
@glennjackman、最後の文は間違っています。Solaris 10は、依然として最も広く展開されているSolarisのバージョンであり、[ "$1" = "" ]まだ動作しません/bin/sh(ただし、使用したいのです/usr/xpg4/bin/shが、ではありません/bin/sh)。ダッシュは2009
。-ステファンシャゼラ14年

8

角カッコはtestを示しているため、構文的には問題あり[ x$1 = x]ませんが、なしifまたは類似のものは意味がありません。

がにx$1展開する場合はtrue、xそうでない場合はfalse に評価することを意図していますが、引用されていないため$1(たとえば) "hey x"の場合、シェルはを参照x = xするため、この構造はまだ安全ではありません。

x = xチェックの目的は、変数が空かどうかを判断することです。これを行うより一般的な方法は、引用符を使用することです。

if [ "$1" = "" ]; then

Bashのテスト演算子-zとは-nまた使用することができますが、それらは、シェルの他のタイプにはあまり移植性があります。1

引用符またはの理由は、x$1左側が何も展開しないようにするためです。これは構文エラーになります。

if [  = x ]  # No good!
if [ "" =  "" ] # Okay.
if [ x = x ] # Also okay.

1.実際にtestは、スタンドアロンユーティリティにすることができますが、ほとんどのシェルは組み込みユーティリティとして実装します。違いをチェックwhich testしてをtype test。GNU / Linuxではman test、ビルトインを参照すると主張しますが、(eg)を呼び出すと/usr/bin/test、そのユーティリティはmanページに記載されている-zおよびなどの機能を実装しているようです-n


1
[ x$1 = x ]がの場合もtrueに評価さ$1れます" -o x"。試してくださいsh -xc '[ x$1 = x ] && echo yes' sh ' -o x'[ x$1 = x ]間違っていると意味がありません。
ステファンシャゼル14年

@StéphaneChazelasThanks SC-編集(2番目のパラ)。
goldilocks 14年

if使用する必要はありません。test使用前または使用後&&||または使用しwhileて結果を調べることができます $?
Jasen

8
[ x$1 = x ]

でのみ意味がありzshます。これは、の連結とxスクリプトの最初の引数を比較しxます。そのため、[コマンド$1は、空であるか提供されていない場合にtrueを返します。

[ $1 = "" ]

で、ために動作しないzsh空の変数がリストコンテキストで引用されていない場合、それはそうならば、代わりに空の引数のすべての引数なしに展開$1未設定または空で、[コマンドは、引数として受け取ることになり[=空の文字列そして]、それは意味をなさないでしょう。[ -z "$1" ]または[ "$1" = "" ]、POSIXシェルのようにでも大丈夫でしょう。

Bourne-like / POSIXシェルで[ x$1 = x ]は、意味がありません。それは何らかの形での連結に適用されるスプリット+グロブ演算子だxし、その結果を期待して、スクリプトの最初の引数と=してx、と]の有効なテスト式構成する[コマンドを。

スクリプトが1つの渡された場合たとえば、" = x -o x ="引数を、[それらの引数を受け取ることになる:[x=x-ox=x]、その[比較として理解するであろうxxしてxxしてtrueを返します。

場合$1した"* *"場合、シェルはに渡す[名前が始まると、現在のディレクトリにコマンドファイルのリストをx(のグロブ拡大x*)非隠しファイル(拡張の後、リスト*)... [できることはほとんどありません意味を成すために。それが賢明なことを行う唯一のケース$1は、ワイルドカードまたは空白文字が含まれていない場合です。

今、あなたが時々見つけるものは次のようなコードです:

[ "x$1" = x ]

$1が空か未設定かをテストするために使用されます。

空または未設定の変数をテストする通常の方法は次のとおりです。

[ -z "$1" ]

しかし、それはいくつかの値のために失敗した$1ような=いくつかの(非POSIX)中[として見られるようにBourneシェルで組み込みのような実装/bin/shのSolaris 10上の前または一部の古いバージョンdash(0.5.4まで)またはshいくつかのBSDの。

それはのでです[見て[-z=]との引数が不足して文句=二項演算子の代わりとしてそれを理解する-z単項演算子を適用=する文字列。

同様に、if is またはの[ "$1" = "" ]一部の実装では失敗します。[$1!(

それらのシェル/ [実装では:

[ "x$1" = x ]

は、の値に関係なく常に有効なテストです$1

[ "" = "$1" ]

そして:

[ -z "${1:+x}" ]

そして

case $1 in "") ...; esac

もちろん、引数が指定されていないことを確認する場合は、次のようにします。

[ "$#" -eq 0 ]

つまり、スクリプトに渡される引数の数を確認します。

今日では、ノート[ -z "$var" ]明確にPOSIXによって指定され、準拠して失敗することはできません[実装(とbashのが[あると何十年もされています)。したがって、POSIX shまたはbashスクリプトでこれに依存できるはずです。


0

x$1は2つの文字列xを連結$1し、$ 1が空の場合、x $ 1はxに等しく、[x $ 1 = x]は結果としてtrueになります。x = yshの文字列を比較するために使用されます


2
いいえx$1は引用されていないので、それらに対して分割とグロビングが実行されます。
ステファンシャゼル14年

0

[ x$1 = x ]$1未設定/ヌル/空の場合はtrueです。
試してみてください:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
そして
TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"


1
[ x$1 = x ]場合も同様です$1例えばです" -o x"。試してくださいsh -xc '[ x$1 = x ] && echo yes' sh ' -o x'[ x$1 = x ]間違っていると意味がありません。
ステファンシャゼル14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.