21

I have a text file that contains something like this:

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

I wrote a script

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

For some reason, the output of the script doesn't output the file line by line but breaks it off at the commas, as well as the newline. Why is cat or "for blah in cat xyz" doing this and how can I make it NOT do this? I know I can use a

while read line
do
   blah balh blah
done < file

but I want to know why cat or the "for blah in" is doing this to further my understanding of unix commands. Cat's man page didn't help me and looking at for or looping in the bash manual didn't yield any answers (http://www.gnu.org/software/bash/manual/bashref.html). Thanks in advance for your help.

4

5 回答 5

25

问题不在于cat,也不在于for循环本身;它是在使用反引号。当你写:

for i in `cat file`

或更好):

for i in $(cat file)

或(在bash):

for i in $(<file)

shell 执行命令并将输出捕获为字符串,将$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
$
于 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

for 循环加上内部字段分隔符(IFS)的更改将按预期读取文件

对于输入

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

For 循环加上 IFS 更改

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 回答