Bash スクリプトと引用

Bash スクリプトと引用

私は bash スクリプトに関する本を何冊か読んでいますが、適切な引用符と の使用法を理解するのに苦労していますIFS。引用符付きのファイル名に関する小さな例で誰か助けていただけないでしょうか。これをコマンド ラインから実行すると、スペースが含まれていてもファイル名が適切に出力されます。

set - *
for i in "$@"; do echo $i; done

これはスペースで分割されるため機能しません。

set - `find . -name "*"`
for i in "$@"; do echo $i; done

以下も同様です:

IFS=$'\0' set - `find . -name "*" -print0`
for i in "$@"; do echo $i; done

IFS=$'\n'とを使用する組み合わせも同様です-print。これらがすべて失敗するのはなぜでしょうか?

次の例も失敗しますが、この場合はエラーが発生します (「bash: 予期しないトークン `do' の近くで構文エラーが発生しています」)。なぜでしょうか?

IFS=$'\n' for i in `find . -name "*" -type f`; do echo $i; done 

しかし、これは機能します (「;」に注意してください)。

IFS=$'\n'; for i in `find . -name "*" -type f`; do echo $i; done 

ファイル名がまったく分割されていないため、これは失敗します (forループは 1 回だけ)。

IFS=''; for i in `find . -name "*" -type f -print0`; do echo -e "$i\n"; done

では、なぜ最初の 1 つ目と 3 つ目の 1 つ目が失敗するのでしょうか?

IFS最後に、 を設定する場合、''は と同じであるという考えは正しいでしょうか$'\0'? (直前の例で両方試しました。) もしそうなら、$'\n'だけではなく が必要なのはなぜでしょうか\n?

*Ubuntu Gnome 16.04ではBashのバージョンは4.3.42(1)です。

答え1

bash コマンドをデバッグする際に学んだことが 2 つあります。1) 期待どおりに動作しない場合は、コマンドを echo/printf して、期待どおりに表示されることを確認します。2) コマンド内にあるコマンドを手動で実行して、正しく実行されるかどうかを確認します (rm、dd、chmod 777 などの潜在的に破壊的なコマンドでない限り)。

具体的に何を、どのように実現しようとしているのですか? 私の場合は、そのコマンドをそのまま実行しても問題なく動作するようです。そのため、何を実行したいのかを説明する必要があります。ファイル名にスペースが含まれているため、コマンドで問題が発生していませんか? IFS 変数からスペースを取り除けば、おそらく希望どおりに動作します。IFS=$'\n\t'この-print0オプションは基本的にすべての行区切り文字を削除するため、ファイル名にスペースが含まれていない限り、これらのコマンドで必要なすべてのものに区切り文字がまったく含まれません。2 番目の質問について:

IFS=$'\n' for i in `find . -name "*" -type f`; do echo $i; done 

このコマンドは、bash が次のように読み取るため、正しく実行されません。

IFS=$'\n' for i in `find . -name "*" -type f`
do echo $i
done

最初の行は IFS を に設定します$'\n' for i in。その後、次の行は と表示されますがdo echo $i、このコマンドは何らかのループを先行コマンドとして必要とするため、機能しませんdo。次の行は、セミコロンが bash にコマンドの終わりに達したことを通知するため、機能します。

IFS=$'\n'
for i in `find . -name "*" -type f`
do echo $i
done 

最後に、IFS を設定するときに、'' は $'\0' と同じであるという考えは正しいでしょうか? (直前の例で両方を試しました。) もしそうなら、なぜ \n だけではなく $'\n' が必要なのでしょうか?

最初の部分はそうです。''と は'\0'どちらも NULL とみなされるため、基本的に同じです。これは、bash が$''ANSI C 文字列として解釈するためです。また、bash が C 文字列として解釈して IFS に改行文字を配置するには、\n を引用符で囲む必要があります。
これらについての詳細は、ここ

関連情報