for
ファイルのループを実行しようとしていますが、行全体を表示したいです。しかし、代わりに最後の単語のみを表示します。完全なラインが欲しい。
for j in `cat ./file_wget_med`
do
echo $j
done
実行後の結果:
Found.
私のデータは次のとおりです。
$ cat file_wget_med
2013-09-11 14:27:03 ERROR 404: Not Found.
for
ファイルのループを実行しようとしていますが、行全体を表示したいです。しかし、代わりに最後の単語のみを表示します。完全なラインが欲しい。
for j in `cat ./file_wget_med`
do
echo $j
done
実行後の結果:
Found.
私のデータは次のとおりです。
$ cat file_wget_med
2013-09-11 14:27:03 ERROR 404: Not Found.
回答:
for
スペース、タブ、改行などの空白が見つかると、ループが分割されます。したがって、IFS(Internal Field Separator)を使用する必要があります。
IFS=$'\n' # make newlines the only separator
for j in $(cat ./file_wget_med)
do
echo "$j"
done
# Note: IFS needs to be reset to default!
unset IFS
他のコマンドがこの同じシェルで影響を受けないように、後でそれが推奨されるようです。
$
意味IFS=$'\n'
ですか?
$
文字列内で改行を機能させます。これもlocal IFS=$'\n'
関数内で行う必要があります。
for
デフォルトでは、空白(スペース、タブ、改行)でループが分割されます。一度に1 行ずつ作業する最も簡単な方法は、while read
代わりにループを使用することです。ループは改行で分割されます。
while read i; do echo "$i"; done < ./file_wget_med
私はあなたのコマンドが1行につき1ワードを吐き出すことを期待しています(それは私自身のファイルでテストしたときに起こったことです)。他に何かが起こっている場合、何が原因であるかはわかりません。
for i in `ls`; do echo $1; done
、whileコマンドに出力をパイプすることによるの優れた代替手段でもありますls|while read i; do echo $i; done
。これは、環境変数を変更する必要なく、スペースを含むファイル/フォルダ名で機能します。非常に良い答えです。
ls
ため、|
(パイプオペレータ)での使用は安全とは見なされません。find
この目的のためにより安全であることに加えて、より柔軟です。
pbpaste | while read t; do echo "<string>$t</string>"; done
ls -1
一緒に使用することができる|
ごとに1つの行フォーマットされていない出力を保証するために
#!/bin/bash
files=`find <subdir> -name '*'`
while read -r fname; do
echo $fname
done <<< "$files"
動作確認済みで、おそらく必要なライナーではありませんが、エレガントに行うことはできません。
次のように書きます。
cat ./file_wget_med | while read -r j
do
echo $j
done
元のスクリプトでの変更が最小限で済むため(を使用するソリューションを除きますが、このループ制御ステートメントだけでなく動作もIFS
変更しbash
ます)。
cat
ここでパイプとは不要です。while
ループはリダイレクションを正常に受け入れます。これが通常、次のように書かれている理由ですwhile IFS= read -r line; do...done < input.txt
マップファイルは、通りのような携帯用ではない、インデックス付きの配列にファイルから行を読み込むための便利な方法です読みが、わずかに速いです。forループを使用すると、サブシェルの作成を回避できます。
#!/bin/bash
mapfile -t < file.txt
for line in "${MAPFILE[@]}"; do
echo $line
done
パイプラインを使用する場合は、whileループをサブシェルに配置することに留意してください。変数のようなwhileループ内の変更は、スクリプトの外側部分には伝播しません。
例:
#!/bin/bash
a=0
printf %s\\n {0..5} | while read; do
((a++))
done
echo $a # 'a' will always be 0.
(より良い解決策):
#!/bin/bash
b=0
while read; do
((b++))
done < <(printf %s\\n {0..5})
echo $b # 'b' equal to 6 (works as expected).
Dandalfは機能的な解決策に近づきましたが、未知の量の入力(つまりfind ~/.gdfuse -name '*'
)の結果を変数に割り当てようとするべきではありません!または、少なくとも配列変数を介してそのようなことをしようとしています。怠け者だと主張するなら!危険な操作なしで行われるダンダルフの解決策は次のとおりです。そして、すべて一行で
while read -r fname; do
echo $fname;
done <<< `find ~/.gdfuse -name '*'