21

次のような内容を含むテキスト ファイルがあります。

abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma

スクリプトを書きました

for i in `cat file`
do
   echo $i
done

何らかの理由で、スクリプトの出力はファイルを 1 行ずつ出力せず、コンマと改行で区切ります。cat または "for blah in cat xyz" がこれを行うのはなぜですか? どうすればこれを行わないようにできますか? 私は私が使用できることを知っています

while read line
do
   blah balh blah
done < file

しかし、UNIXコマンドの理解を深めるために、catまたは「for blah in」がこれを行っている理由を知りたいです。Cat の man ページは役に立ちませんでした。また、bash マニュアルを調べたりループしたりしても、答えは得られませんでした ( http://www.gnu.org/software/bash/manual/bashref.html )。よろしくお願いします。

4

5 に答える 5

25

問題はcatにも、forループ自体にもありません。それは逆引用符を使用しています。次のいずれかを書く場合:

for i in `cat file`

または(より良い):

for i in $(cat file)

または (でbash):

for i in $(<file)

シェルはコマンドを実行し、出力を文字列としてキャプチャし、 の文字で単語を区切ります$IFS。に入力する行が$i必要な場合は、いじるか、ループをIFS使用する必要があります。処理されるファイルが大きくなる危険性がある場合は、ループの方が適切ですwhilewhileを使用するバージョンとは異なり、ファイル全体を一度にメモリに読み込む必要はありません$(...)

IFS='
'
for i in $(<file)
do echo "$i"
done

を囲む引用符は、"$i"一般的には良い考えです。このコンテキストでは、変更された$IFSでは実際には重要ではありませんが、良い習慣は良い習慣です。次のスクリプトで重要です。

old="$IFS"
IFS='
'
for i in $(<file)
do
   (
   IFS="$old"
   echo "$i"
   )
done

データ ファイルの単語間に複数のスペースが含まれている場合:

$ cat file
abc                  123,         comma
the   quick   brown   fox
jumped   over   the   lazy   dog
comma,   comma
$ 

出力:

$ sh bq.sh
abc                  123,         comma
the   quick   brown   fox
jumped   over   the   lazy   dog
comma,   comma
$

二重引用符なし:

$ cat bq.sh
old="$IFS"
IFS='
'
for i in $(<file)
do
   (
   IFS="$old"
   echo $i
   )
done
$ sh bq.sh
abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
$
于 2013-06-14T06:12:06.190 に答える
6

変数を使用IFSして、フィールド区切り文字として改行を指定することができます。

IFS=$'\n'
for i in `cat file`
do
   echo $i
done
于 2013-06-14T02:45:21.003 に答える
4
cat filename | while read i
do
    echo $i
done
于 2020-03-26T14:24:37.290 に答える
3

内部フィールドセパレーター(IFS)の変更と組み合わせたforループは、意図したとおりにファイルを読み取ります

入力用

abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma

IFS 変更と結合された for ループ

old_IFS=$IFS
IFS=$'\n'
for i in `cat file`
do
        echo $i
done
IFS=$old_IFS

結果は

abc 123, comma
the quick brown fox
jumped over the lazy dog
comma, comma
于 2013-06-14T02:45:01.013 に答える
2

IFS - 内部フィールドセパレーターを設定して、必要なものを取得できます。

行全体を一度に読み取るには、IFS="" を使用します。

于 2013-06-14T02:05:24.760 に答える