通常、readコマンドを使用して、入力ファイルをシェルスクリプトに1行ずつ読み取ります。入力ファイルblah.txtの最後の行の最後に新しい行が挿入されていない場合、次のようなサンプルコードは間違った結果をもたらします。
#!/bin/sh
while read line
do
echo $line
done <blah.txt
したがって、入力ファイルが次のように読み取った場合-
One
Two
Three
Four
そして、4の後、リターンを押さないと、スクリプトは最後の行の読み取りに失敗し、印刷します
One
Two
Three
4の後に余分な空白行を残すと、次のようになります。
One
Two
Three
Four
//blank line
出力には、Fourを含むすべての行が印刷されます。ただし、これはcat
コマンドを使用して行を読み取る場合には当てはまりません。最後を含むすべての行が印刷され、最後に余分な空白行を追加する必要はありません。
なぜこれが起こるのかについてのアイデアはありますか?私が作成するスクリプトはほとんどが他の人によって実行されるため、すべての入力ファイルの最後に余分な空白行を追加する必要はありません。
私は何年もの間これを理解しようとしてきた。解決策があれば感謝します(もちろん、cat
コマンドは1つですが、読み取りの背後にある理由も機能しません)。
read
は、改行文字またはファイルの終わりが見つかるまで読み取り、ファイルの終わりが検出されるとゼロ以外の終了コードを返します。そのため、行を読み取り、ゼロ以外の終了コードを返すことは非常に可能です。
したがって、入力が改行で終了しない可能性がある場合、次のコードは安全ではありません。
while read LINE; do
# do something with LINE
done
while
の本体は最後の行で実行されないためです。
技術的に言えば、改行で終了していないファイルはテキストファイルではないため、このようなファイルではテキストツールが奇妙な方法で失敗する可能性があります。しかし、私はいつもその説明に頼るのを嫌がります。
問題を解決する1つの方法は、読み取られたものが空でないかどうかをテストすることです(-n
):
while read -r LINE || [[ -n $LINE ]]; do
# do something with LINE
done
他の解決策には、mapfile
を使用してファイルを配列に読み込み、最後の行を適切に終了することが保証されているユーティリティを介してファイルをパイプすることが含まれます(grep .
、たとえば、空白行を処理したくない場合)、またはawk
(通常は私の好みです)のようなツールを使用して反復処理を実行します。
ご了承ください -r
は、ほぼ確実にread
ビルトインで必要です。 read
が再解釈しないようにします\
-入力のシーケンス。
DONE=false
until $DONE
do
read line || DONE=true
echo $line
done < blah.txt
1行の回答:
IFS=$'\n'; for line in $(cat file.txt); do echo "$line" ; done
次のようなwhileループを使用します。
while IFS= read -r line || [ -n "$line" ]; do
echo "$line"
done <file
または、whileループでgrep
を使用します。
while IFS= read -r line; do
echo "$line"
done < <(grep "" file)
grep .
の代わりにgrep ""
を使用すると、空の行がスキップされます。
注意:
IFS=
を使用すると、行のインデントはそのままになります。
最後に改行のないファイルは、標準のUNIXテキストファイルではありません。
リダイレクトされた「while-read」ループを使用した以下のコードは私のためにうまく機能します
while read LINE
do
let count++
echo "$count $LINE"
done < $FILENAME
echo -e "\nTotal $count Lines read"