web-dev-qa-db-ja.com

catを使用して、各行に区切り文字がある行ごとにファイルを読み取ることができないのはなぜですか

次のようなものが含まれているテキストファイルがあります。

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 xyzのblah」がこれを行っているのはなぜですか。また、これを行わないようにするにはどうすればよいですか。私は使用できることを知っています

while read line
do
   blah balh blah
done < file

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

17
Classified

問題はcatにも、forループ自体にもありません。逆引用符を使用しています。あなたがどちらかを書くとき:

_for i in `cat file`
_

または(より良い):

_for i in $(cat file)
_

または(bash内):

_for i in $(<file)
_

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

_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
$
_
20

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

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

内部フィールド区切り文字(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
3
Dan675

IFS-内部フィールド区切り文字を設定して、必要なものを取得できます。

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

2
Sudheej
cat filename | while read i
do
    echo $i
done
0
user2954660