13

を使用して複数行のシェル コマンドを評価しようとしていますがeval、改行で区切られた eval で変数を解決しようとすると\n、変数が解決されません。

x='echo a'
y='echo b'
z="$x\n$y"
eval $x
eval $y
eval $z

どの出力:

a
b
anecho b

最後のコマンドは を与えanecho b、どうやらそこにある\nものとして扱われたようnです。それで、複数行のコマンドを評価する方法はありますか(たとえば、で区切られてい\nます)?

4

6 に答える 6

13

\n改行ではありません。これは、場合によっては改行に変換されるエスケープ シーケンスですが、そのような状況では使用していません。変数$zには改行が含まれず、バックスラッシュの後に「n」が続くだけです。その結果、これが実際に実行されているものです。

$ echo a\necho b
anecho b

代わりにセミコロンを使用するか (翻訳を必要としません)、改行に翻訳されるコンテキスト\nで使用できます。

$ newline=$'\n'
$ x='echo a'
$ y='echo b'
$ z="$x$newline$y"
$ eval "$z"
a
b

前後の二重引用符に注意して"$z"ください。ここでは実際に重要です。それらがないと、bash は の値を単語分割し、$zすべての空白 (スペース、タブ、改行) を単語の区切りに変えます。その場合、evalは "echo" "a" "echo" b" という単語を受け取り、効果的に改行をスペースに変換します。

$ eval $z
a echo b

これは、変数参照を二重引用符で囲むことが重要なケースの長いリストのもう 1 つです。

于 2013-07-24T14:34:32.943 に答える
3

少し異なるアプローチ:

read -r -d '' script <<'EOF'
echo a
echo b
EOF

eval "$script"

出力

a
b

説明

  • read -r -d '' script
    • -r- バックスラッシュで文字をエスケープしないでください
    • -d ''- 改行ではなく、DELIM の最初の文字が読み込まれるまで続行します (EOF まで読み込まれます)。
    • script- 結果を保存する変数の名前
  • <<'EOF'- 変数展開なしでヒアドキュメントを使用する (一重引用符で囲むとEOF変数展開が停止します)

これは を使用して行うこともできます$(cat <<'EOF'...EOF)が、この方法では不必要に cat を使用せず、サブシェルも使用しません。

役に立たない猫の例:

script=$(cat <<'EOF'
echo a
echo b
EOF
)

eval "$script"
于 2019-08-27T04:37:05.663 に答える
3

xおよびy変数に printf などによって処理されるシーケンスが含まれている場合、必ずしも最適な方法ではありません%sが、とにかく、\nセパレーターとして保持しながらそれを行う方法を次に示します。

x='echo a'
y='echo b'
z="$x\n$y"
eval $x
eval $y
export IFS=" "
eval $(printf "$z")

プリント:

a
b
a
b
于 2013-07-23T21:33:45.653 に答える