我想逐行阅读文本文件,这里有两种方法:
这个方法工作正常,逐行读取文本,我知道它使用read
命令
readarray -t files < c.txt
for i in "${files[@]}"; do
printf '%s\n' "$i" >> 2.txt
read -p 'press enter to continue'
done
但是这个方法一次读取所有文件而不是逐行读取!
for i in "$(<c.txt)"; do
printf '%s\n' "$i" >> 1.txt
read -p 'press enter to continue'
done
如果我删除"$(<c.txt)"
中的双引号并使用IFS=$'\n'
和set -f
,则会按预期逐行阅读文字。
问题:
为什么当我使用"${files[@]}"
时,它逐行读取,为什么for
有不同的行为?
此示例中使用的文本文件:
$ cat c.txt
this is a test
)=_ç)çà)èç(-è_-'é²"²2°4.²&é (§/%Mµ%µ¨£¨P£
trailing space
tab
#comment
*
echo test
答案 0 :(得分:1)
使用for
的问题在于它对行没有任何了解 - for
期望得到一个“单词”列表来迭代。如果使用for i in "$(<c.txt)"
,则双引号会告诉shell不要对文件内容进行任何解析,因此整个内容将被视为单个单词。另一方面,如果你不使用双引号(for i in $(<c.txt)
),shell会将文件内容拆分为由空格分隔的“单词”(默认情况下表示空格,制表符和换行符),然后尝试将包含通配符的任何单词扩展为匹配文件名列表。你可以调整shell选项,使这个拆分和扩展过程更像你想要的那样,但从根本上说它是为了做其他事情而且最多只是一个kluge。
如果要从文件中读取行,请使用用于从文件中读取行的内容。 read
和readarray
都是为此目的而设。有他们自己的怪癖,你可能需要解决,但他们至少从正确的区域开始; for
确实没有。顺便说一下,BashFAQ entry you linked对于ffmpeg等问题有一个非常好的解决方法:
while read -r line <&3; do
...
done 3<file
您提供的readline
方法也可以正常使用,但不是那么便携。 readline
所做的是将整个文件读入一个shell数组,每行作为一个单独的数组元素。然后"${files[@]}"
告诉shell扩展数组内容,每个数组元素都被视为一个单独的单词。因此,行成为数组元素,它们变成“单词”,这是for
迭代的东西,并且你得到了预期的结果。