変数の拡張は、変数のあるコンテキストによって異なる動作をしますか?

変数の拡張は、変数のあるコンテキストによって異なる動作をしますか?

私が次のことをしているとしましょう。

IFS=,
x="hello,hi,world"
y=$x

y文字列があるため、次のように置き換えられますhello hi worldy=$x

y="hello hi world"

それでは、次のスクリプトがあるとしましょう。

IFS=,
x="hello,hi,world"
if [ $x = "hello hi world" ]
then
    echo "equal"
fi

上記のスクリプトを実行すると、次のエラーが発生します。

test.sh: line 3: [: too many arguments

私はステートメントが実行されたときに置き換えられるのではなく置き換えられるので、if [ $x = "hello hi world" ]このエラーが発生すると仮定します。if [ hello hi world = "hello hi world" ]if [ "hello hi world" = "hello hi world" ]

これは、変数が$xそのコンテキストに応じて2つの異なる方法(二重引用符がある場合と二重引用符がない場合)に拡張されることを意味します。

私は正しいですか?

答え1

yひもがあるでしょう。hello hi world

いいえ、できません。変数割り当ての拡張は、単語分割やファイル名のグロービングの影響を受けません。 (ある意味、常に二重引用符で囲まれているように動作します。)以下を参照してください。いつ二重引用符が必要ですか?

$ IFS=,
$ x="hello,hi,world"; y=$x
$ echo "$y"
hello,hi,world

if [ $x = "hello hi world" ]ステートメントが次に置き換えられたため、このエラーが発生したとします。if [ hello hi world = "hello hi world" ]

はい、そうです。テキストベースの置換ではありませんが、ここで参照されていないため、トークン化され、$xコマンドは予想される4つの代わりに6つの[異なる引数(hello、、、、、および)を確認します。hiworld=hello hi world]

答え2

割り当てに変数を使用すると、参照に関して異なる動作をします。存在する

y=$x

噴射を行いません。つまり、次のようになります。

y="$x"

ただし、一般的なパラメータ拡張では次のようになります。

if [ $x =

引用符があるかどうかは違いがあります。注:引用符を使用すると拡張されませ$x"hello hi world""hello,hi,world"、。

答え3

変数の割り当て中はトークン化は発生しませyhello,hi,world。ただし、単語の分離は内部的に発生し[]、設定した後は別の単語IFS=,に展開されます。hello hi world

問題は[、特定の数の引数が必要であることです。タグを付けたので、bash高度なコマンドを使用して[[ ]]単語の区切りを無効にするとエラーは発生しません。

実際にペアをトークン化するには、x次のようにしますy="$(IFS=','; echo $x)"。これhello hi worldはに単語として割り当てられますy

答え4

引用の問題があります:

  1. 変数拡張:

    yはhello hi worldという文字列を受け取ります。

    いいえ、そうではありません。しかし、エコーがあります。引用しない次の値を印刷します。

    $ IFS=,
    $ x="hello,hi,world"
    $ y=$x
    $ echo $y
    hello hi world
    

    はい、IFS文字(,)は変数拡張を区切り、echoは引数の間にスペースを入れます。詳しく確認してください。

    $ printf '<%s>\n' $y
    <hello>
    <hi>
    <world>
    

    ただし、参照される拡張はIFSまたは分割によって変更されません。

    $ echo "$y"
    hello,hi,world
    $ printf '<%s>\n' "$y"
    <hello,hi,world>
    
  2. テストライン

    [ $x = "hello hi world" ]
    

    ここでも同じ参照問題が発生し、変数が拡張されます。そしてマロ。行は次のとおりです。

    [ hello hi world = "hello hi world" ]
    

    3つのパラメータ「hello」、「hi」、および「world」は正しいテスト構造に解析できません。

    ただし、これは次のことを行います。

    $ y=hello,=,world,-o,hello
    $ [ $y = "hello" ] && echo yes || echo no
    yes
    

    実行される内容は次のとおりです。

    [ hello = world -o hello = "hello" ] && echo yes || echo no
    

    引用すると、分割を避けることができます。

    $ y=hello,hi,world
    $ [ "$y" = "hello,hi,world" ] && echo yes || echo no
    yes
    

    次の設定では、[[分割を避けることもできます。

    $ y=hello,hi,world
    $ [[ $y == "hello,hi,world" ]] && echo yes || echo no
    yes
    
  3. あなたの問題:

    私は正しいですか?

    いいえ、変数は毎回同じ方法で展開されます。

長い話を短く

拡張機能を引用してください。

関連情報