回答:
説明する必要があるのは、コマンドが終了コードではなく機能しているように見えることです
'\n'
バックスラッシュ\と文字の2つの文字nです。あなたが必要だと思っ$'\n'
たのは、改行であるです(しかし、それも正しくありません。以下を参照してください)。
-d
オプションは、この処理を行います。
-d delim continue until the first character of DELIM is read, rather than newline
したがって、そのオプションがない場合、read
改行まで読み取り$IFS
、区切り文字としての文字を使用して行を単語に分割し、単語を配列に入れます。指定した場合-d $'\n'
、行区切り文字を改行に設定しても、まったく同じことになります。設定と-d '\n'
は、最初のバックスラッシュまで読み取ります(ただし、もう一度、以下を参照)。これは、の最初の文字ですdelim
。ファイルにはバックスラッシュがないため、はファイルread
の終わりで終了します。
Exit Status:
The return code is zero, unless end-of-file is encountered, read times out,
or an invalid file descriptor is supplied as the argument to -u.
そのため、終了コードは1です。
コマンドが機能したと思われるという事実から、ファイルにスペースがないと結論付けることができます。そのためread
、バックスラッシュを見つけるという無駄な希望の中でファイル全体を読んだ後、空白(デフォルト値の$IFS
)、改行を含む。したがって、各行(または行に複数の単語が含まれている場合は各単語)が配列に格納されます。
潜入バックスラッシュの謎の事件
さて、ファイルにバックスラッシュが含まれていないことをどのようにして知りましたか?-r
フラグを指定しなかったためread
:
-r do not allow backslashes to escape any characters
したがって、ファイル内にバックスラッシュがある場合、2つ続けて配置しない限り、それらは取り除かれます。そしてもちろん、read
終了コードが1であったという証拠があります。これは、バックスラッシュが見つからなかったことを示しているため、2つが連続していませんでした。
テイクアウェイ
ほぼすべてのコマンドの後ろに隠れていなければならないことがなければ、bashはbashにはなりませんread
。これも例外ではありません。ここにカップルがあります:
を指定しない限り-r
、read
はバックスラッシュのエスケープシーケンスを解釈します。それが実際に必要な場合を除いて(たまにそうですが、たまにしかありません)、-r
入力にバックスラッシュがあるまれなケースで文字が消えないように指定することを忘れないでください。
read
終了コード1 を返すという事実は、それが失敗したことを意味しません。ラインターミネーターを見つけることを除いて、それは成功したかもしれません。したがって、次のようなループには注意してください。最後の行の最後に改行がないというまれなケースでは、最後の行でwhile read -r LINE; do something with LINE; done
失敗するためdo something
です。
read -r LINE
バックスラッシュは保持されますが、先頭または末尾の空白は保持されません。
while read
。そうでなければ、素晴らしい答え。
while read
ループ内に何もない限り使用できます。そうでなければ、それはあなたを噛むのを待っているバグです-そして私を信じて、私は噛まれました。
read
。
mapfile
は、かなりクールです。簡単で汚いハックのために、私は禁止されたwhileループを使用しますが、それを本番スクリプトに入れるのをやめました。YMMVと私は答えの警告を和らげました。