stdinから読み取らなくても、読み込みループは最初の行の後に停止します。

stdinから読み取らなくても、読み込みループは最初の行の後に停止します。

testContainsというファイルがあります。

test
test

このコマンドを実行しています。

while read line
do
echo "$line"
done </tmp/test

これは「test」を2回出力する必要がありますが、一度だけ出力します。使用してもwhile IFS= read -r line何も変わりません。これを解決する方法は、3番目の空白行を出力することですが、関係なく動作するはずです。

答え1

努力する:

while IFS='' read -r line || [ "$line" ]

はい、標準入力(stdin)から読み取られ、<teststdinにリダイレクトされます。

おそらく何が起こっているのかは、読み取りがテキストファイルを処理するように設計されていることです。正しいテキストファイルは改行文字で終わる必要があります。

何かを作る改行文字のファイル終了結果は非常に高速です。:

[ -n "$(tail -c1 file)" ] && printf '\n' >>file 

ただし、ファイルが欠落していて改行文字を追加するためにファイルを編集できない場合、解決策は(追加で)内容を読み取ったかどうかをテストすることです。

while read line || [ "$line" ]

これは読み込みに失敗しましたが(新しい行を読み取らず(デフォルト)、ファイルの終わりに到達)、何かを読み取ると"$line"ループが実行されます。

改行文字で終わるファイルかどうかにかかわらず、うまく機能します。

いいえ、aはIFS='' read実際に最後の行の読み取りに(直接的に)影響しませんIFS=''(デフォルトIFSと比較)。[ㅏ]スペース、タブ、改行)は分割にのみ影響します。一部変数(先行および/または末尾の空白の削除に影響を与える場合を除く(IFSに空白のみが含まれている場合))[雨])).変数()は1つだけなので、"$line"分割を行う必要はありません。

読み取りオプション-d(2.04以降のbashにあります)も役に立ちません。一致させる特定の「ファイルの終わり」文字はありません(最後のバイトは任意の文字である可能性があります)。

残りの唯一のオプションは次のとおりです。

  • 正しいテキストファイルになるようにファイルを回復してください。
  • 変数で読み取った内容があるかどうかをテストしますline

これで正しいスクリプトは次のようになります。

#!/bin/bash
while IFS='' read -r line || [ "$line" ]
do
    printf '%s\n' "$line"
done <test

IFS = ''は、IFSの異常な値による問題を回避するために使用されます。


[1][2]もちろん、IFSに値がある場合は、他の多くの文字を削除することもできます。 try("x"で終わる値の場合)

printf "test\ntesx\ntest" | while IFS="x" read -r line || [ "$line" ]; do echo "$line"; done

いいえ、zshは他のことを行います。

関連情報