为什么不能使用cat逐行读取文件,其中每行都有分隔符

时间:2013-06-14 01:39:57

标签: linux bash for-loop cat

我有一个包含以下内容的文本文件:

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

我写了一个剧本

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

由于某种原因,脚本的输出不会逐行输出文件,而是在逗号和换行符处将其分开。为什么猫或“为cat xyz中的等待”这样做,我怎么能不这样做呢?我知道我可以使用

while read line
do
   blah balh blah
done < file

但我想知道为什么cat或“for blah in”这样做是为了进一步理解unix命令。 Cat的手册页对我没有帮助,并且在bash手册中查找或循环没有得出任何答案(http://www.gnu.org/software/bash/manual/bashref.html)。在此先感谢您的帮助。

5 个答案:

答案 0 :(得分:19)

问题不在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
$

答案 1 :(得分:5)

您可以使用IFS变量来指定您想要换行符作为字段分隔符:

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

答案 2 :(得分: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

答案 3 :(得分:2)

IFS - 可以设置内部字段分隔符以获得所需内容。

要一次阅读整行,请使用: IFS = “”

答案 4 :(得分:1)

cat filename | while read i
do
    echo $i
done