この記事:関数に引数をそのまま正確に渡します。
ただし、設定が若干異なります。
私は3つのbash機能、foo、bar、bazを持っています。その設定は次のとおりです。
foo() {
bar $1
}
bar() {
var1=$1
var2=$2
echo "$var1" test "$var2"
}
export ENV_VAR_1="1"
export ENV_VAR_2="2 3"
foo "${ENV_VAR_1} ${ENV_VAR_2}"
私の予想結果は次のとおりです。
1 test 2 3
ただし、出力は次のようになります。
1 test 2
私はこれがなぜそうなのか理解しています。 barは次のように実行されます。
bar 1 2 3
私の質問は:それを実行する方法です
bar 1 "2 3"
私が試したこと:
foo () {bar "$1"}
# Out: 1 2 3 test. Makes sense since "1 2 3" is interpreted as a single argument.
答え1
これは文字列を引数として提供しますfoo
。
foo "${ENV_VAR_1} ${ENV_VAR_2}"
$1
引用符内にないため、シェルは単語の区切りを実行するため、次の3つの引数が提供されますbar
。
bar $1
S1
トークン化は、これらの文字の元のソースに関係なく実行されます。
より簡単な例
これを次のように定義しましょうx
。
$ x="${ENV_VAR_1} ${ENV_VAR_2}"
今印刷してみましょう"$x"
:
$ printf "%s\n" "$x"
1 2 3
ご覧のとおり、パラメータ"$x"
として解釈されます。これとは対照的に、次の点を考慮してください。
$ printf "%s\n" $x
1
2
3
上記では、$x
3つのパラメータを生成するとトークン化が行われます。
シェル文字列には記録の概念はありません。文字列には、割り当てられる前に文字列の一部という記録はx
ありません。文字列は、スペース、スペースでのみ構成され、単語分割はスペースで機能します。2 3
x
x
1
2
3
代替案:独自のIFSを選択してください
これにより、所望の出力が生成される。
$ foo() ( IFS=@; bar $1; )
$ foo "${ENV_VAR_1}@${ENV_VAR_2}"
1 test 2 3
で にfoo
設定しました。したがって、その後のすべての単語分割は、単語区切り記号を使用して実行される。したがって、呼び出し時に単語の分割が必要な場所に配置します。IFS
@
@
foo
@
答え2
foo
5文字の文字列である1つの引数を関数に渡します1 2 3
。 3つの数字をスペースで区切ります。foo
これらのスペースを別々に扱う理由はありません。
個々の文字列を組み合わせるか内部で使用${ENV_VAR_1}
する${ENV_VAR_2}
と、情報が失われます。失われた情報を回復するには魔法が必要ですが、コンピュータはそうすることはできません。1 2
との間の分離を維持するには、呼び出し方法を3
変更する必要があります。foo
2つの別々のパラメータを渡します。
foo "${ENV_VAR_1}" "${ENV_VAR_2}"
もしそうなら、あなたがしなければならないことは参照の修正通貨bar
。 2つのパラメータを渡します。
foo () {
bar "$1" "$2"
}
または、引数全体のリストを渡します。
foo () {
bar "$@"
}