Bashのマニュアルページには、組み込み機能について次のように記載されていますread
。
ファイルの終わりが発生しない限り、終了ステータスは0です。
-e
オプションを設定して次のコードを使用したので、最近これが私を悩ませました。
read -rd '' json <<EOF
{
"foo":"bar"
}
EOF
この場合、失敗したシャットダウンが必要な理由を理解できません。これはどのような状況で役に立ちますか?
答え1
read
レコードを読み取り(デフォルトは減りますが、ksh93 / bash / zshは-d
zsh / bashを使用するときにNULも含む他の区切り文字を受け入れます)、レコード全体を読み取る限り成功を返します。
read
EOF が見つかったがまだレコード区切り文字に出会っていない場合は、ゼロ以外の値を返します。
これにより、次のことができます。
while IFS= read -r line; do
...
done < text-file
またはzsh / bashを使用してください
while IFS= read -rd '' nul_delimited_record; do
...
done < null-delimited-list
最後のレコードを読んだ後、ループは終了します。
以下を使用して、最後に完了した履歴以降にさらに多くの[ -n "$nul_delimited_record" ]
データがあることを確認できます。
お客様の場合はread
NUL 文字が含まれていないため、入力にレコードは含まれません。bash
この文書にはNULを含めることはできません。したがって、read
レコード全体が正常に読み取られなかったため、失敗します。json
EOF(IFS処理後)まで読み取った内容を変数に保存し続けます。
とにかくread
設定せずに使用することはほとんど意味がありません$IFS
。
詳細については、次を参照してください。「IFS=read-r-line」を理解する。
答え2
これが私が自分自身を使用しない理由の1つですset -e
。
与えられたEOL区切り文字なしでEOFに達すると、読み取りは1を返すことがわかったので、次のいずれかを実行できます。
# depending on the contents of the input, it's an error
# if no data was read:
IFS= read -rd '' json <<EOF || [[ -n $json ]]
...
EOF
# or, you don't care at all how much data was read
IFS= read -rd '' json <<EOF || :
...
EOF
答え3
既定では、読み取りコマンドはユーザー入力の行をターゲットにしていますが、ファイルで機能するには、行末区切り文字に達する前にファイル内のすべてのデータが消費されたときを検出できる必要があります。
あなたの例では、EOFという単語は、リダイレクト演算子のインラインテキストを区切るために使用されます。<<そして、文書に記載されている「ファイルの終わり」マークを読むこととは何の関係もありません。ただし、データが最後の行の改行文字(クローズ中括弧を含む)の後に終わるという信号をインタプリタに送信するほかはありません。もちろん、その構成は完全なデータを持っていてファイルから来たものではないため、ファイルの終わりがデータの突然の終わりになる状況はあり得ません。
したがって、読み取りマニュアルページの指示はここでは実際には適用されず、エンドをeofとしてマークできるファイルまたはデータソースから読み取った場合(ユーザーが[Ctrl-D]を押すか、最後に到達した場合など)を読み取ることができます。あります。パイプラインの他のコマンドから来ます)。
これは、d オプションと r オプションの特別な動作と組み合わせられます。 -dは行の終わりに関係なく可能なすべてを読み取ることができます(ここでは必要だと思います)、-tは読み取りでバックスラッシュエスケープ文字を無視するようにします(テキストには存在しません)。 「bar」に埋め込まれたバイナリデータや印刷できない文字などの特殊文字が必要な場合を除き、テキストは引用符内にあるため必要ありません。したがって、ファイルをデータソースとして使用すると、明らかに動作しません。