このファイルがあるとしましょう:
hello world hello world
このプログラム
#!/bin/bash for i in $(cat $1); do echo "tester: $i" done
出力
tester: hello tester: world tester: hello tester: world
for
は、空白を無視して各行を個別に繰り返します。つまり、最後の2行は次のように置き換える必要があります
tester: hello world
引用符を使用for i in "$(cat $1)";
の結果i
にファイル全体が一度に割り当てられます。何を変更すればよいですか?
回答
(9年後:)
提供された両方の回答は、最後に新しい行がないファイルでは失敗します。これにより、最後の行が事実上スキップされ、エラーが発生せず、災害につながります(一生懸命学習しました)方法:)。
これまでに見つけた「JustWorks」(bashとshの両方)の最も簡潔なソリューション:
while IFS="" read -r LINE || [ -n "${LINE}" ]; do echo "processing line: ${LINE}" done < /path/to/input/file.txt
より詳細な説明については、次のStackOverflowの説明を参照してください:使用方法 “whileファイルの最後に改行がない場合にファイルの最後の行を読み取るには、「read」(Bash)を使用しますか?
注意:このアプローチでは、最後の行に改行がある場合に追加の改行が追加されます。まだありません。
コメント
- いいですね、ありがとうございます。 "まだ改行がない場合は、EOFに改行が追加されることに注意してください。" コメントですが
- トビアス、私は'これをメモとして追加します、ありがとうございます。
回答
for
および IFSを使用:
#!/bin/bash IFS=$"\n" # make newlines the only separator set -f # disable globbing for i in $(cat < "$1"); do echo "tester: $i" done
ただし、改行はIFS空白文字であるため、空の行はスキップされることに注意してください。そのうちの1つは1としてカウントされ、先頭と末尾のものは無視されます。 zsh
とksh93
(bash
ではない)を使用すると、
改行を特別に処理しないようにします。ただし、すべての末尾改行文字(末尾の空行を含む)は、コマンド置換によって常に削除されることに注意してください。
またはとread
(これ以上cat
):
#!/bin/bash while IFS= read -r line; do echo "tester: $line" done < "$1"
空の行は保持されますが、改行文字で適切に区切られていない場合、最後の行がスキップされることに注意してください。
コメント
- ありがとう、'
<
をループ全体に。今では完全に理にかなっていますが -
IFS \ read -r line' in second example. Is really
IFS = `が必要ですか?while read -r line; do echo "tester: $line"; done < "$1"
- @GrzegorzWierzowiecki
IFS=
は、先頭と末尾の空白の削除をオフにします。while IFS= read..
で、IFSが効果を発揮しないのはなぜですか? - @BenMaresグロブを防ぐため読んでいるテキストに、展開されて一致するファイル名に表示される可能性のある式。たとえば、
printf '%s\n' '*o' 'bar' >afile; touch foo; IFS=$'\n'; for i in $(cat afile); do echo "$i"; done
を試してください。 -
while IFS= read -r line || [ "$line" ]; do
は、改行文字で適切に区切られていない末尾の行を処理します。 (ただし、追加されます)。