'eval'は、次のコマンドのリダイレクトされた部分にシェルを適用しますか?

'eval'は、次のコマンドのリダイレクトされた部分にシェルを適用しますか?

evalコマンドと一緒に使用すると、evalコマンドのリダイレクト部分にシェルが2回適用されますか?

リダイレクトのファイル名にスペースが含まれていると仮定すると、すべてのeval解析、シェル拡張、およびトークン化フェーズが複数回適用されると、ファイル名は2番目のトークン化フェーズで2つの単語に分割されます。

eval次の例は、次のコマンドのリダイレクト部分にシェルが2回適用されないため、ファイル名が2つの単語に分割されないことを意味しますか?

$ filename="my file"
$ eval "cat" < "$filename"
hi

答え1

提供された例で唯一のことは、evalリダイレクトcatが外部で発生evalし、ファイルがコマンドの標準入力として提供されることですeval "cat"

1つの変形は、単一引用符を使用してリダイレクトを含むコマンド全体を引用することです。

$ eval 'cat < "$filename"'
hi

evalリダイレクトと変数名を含む完全な文字列が取得されるため、変数の拡張だけでなく、スペースを含む必須ファイル名参照も実行されます。これはまだ動作します。

別のオプションは、文字列に二重引用符を使用することです。

$ eval "cat < '$filename'"
hi

変数はシェルによって拡張されますが、変数内の引用符はファイル名を一緒に保持するため、まだ機能します。 (ファイル名にアポストロフィが含まれていると壊れることがあります。)

「動作しないもの」は次のとおりです。

$ eval "cat" "<" "$filename"

これはあなたの例と似ていますが、引用符を使用すると<外部シェルはリダイレクトを実行しません。evalその後、パラメーターを一緒に入れると、結果コマンドは次のようになります。

cat < my file

my fileこれで、引用符が消えたため、期待どおりに機能しません。

答え2

どのように機能するかは、eval実行するシェルコマンドにパラメータを一緒に設定することです。変数の後filename 引用されると、単語分割は行われません。いつこれコマンドは実行するように書かれています。

ファイル名にスペースが含まれている場合は同じことはありません。引用符なしで拡張するとエラーが発生します。例えば

filname=my\ file
echo "dude" > my\ file
eval cat < $filename
bash: $filename: ambiguous redirect

ここで行われたトークン化とcat入力リダイレクトの間違ったファイル名を受け取り、エラーが発生したことに注意してください。

また、リダイレクトなしで使用するcat場合、またはファイルから直接使用している場合は、eval2つのファイルが開きます。cat

eval cat $filename

ランに切り替えます

cat my file

たとえば、指定されたファイルが現在のディレクトリにある場合は、その内容を表示し、指定されたfileファイルが存在しないというエラーストリームを表示します。my

filename=my\ file
echo "foo" > file

myファイルが存在しないようにしています。

eval cat $filename 2>&1
cat: my: No such file or directory
foo

関連情報