我通常使用read命令逐行将输入文件读入shell脚本。如果在输入文件blah.txt的最后一行末尾没有插入新行,则下面这样的示例代码会产生错误的结果。
#!/bin/sh
while read line
do
echo $line
done <blah.txt因此,如果输入文件读取如下内容-
One
Two
Three
Four并且我没有在四次之后按回车键,脚本无法读取最后一行,并打印
One
Two
Three如果我在四个之后多留一个空行,比如,
One
Two
Three
Four
//blank line输出将打印所有行,包括四行。但是,当我使用cat命令读取行时,情况并非如此;打印包括最后一行在内的所有行,而不必在末尾添加额外的空行。
有人知道为什么会发生这种情况吗?我创建的脚本主要由其他人运行,所以他们没有必要在每个输入文件的末尾添加额外的空行。
多年以来,我一直在尝试解决这个问题;如果您有任何解决方案,我将不胜感激(当然,cat命令就是其中之一,但我想知道read不能正常工作的原因)。
发布于 2013-06-24 12:46:36
read将一直读取,直到找到换行符或文件末尾,如果遇到文件末尾,则返回非零退出代码。所以它很有可能同时读取一行并返回一个非零的退出代码。
因此,如果输入可能未以换行符终止,则以下代码是不安全的:
while read LINE; do
# do something with LINE
done因为while的主体不会在最后一行执行。
从技术上讲,不以换行符结尾的文件不是文本文件,文本工具在这样的文件上可能会以奇怪的方式失败。然而,我总是不愿意回到那个解释上来。
解决这个问题的一种方法是测试读取的内容是否是非空的(-n):
while read -r LINE || [[ -n $LINE ]]; do
# do something with LINE
done其他解决方案包括使用mapfile将文件读取到一个数组中,通过某个工具(例如,grep .,如果您不想处理空行,则可以保证正确终止最后一行)通过管道传输文件,或者使用像awk这样的工具进行迭代处理(这通常是我的首选)。
请注意,在read内置中几乎肯定需要-r;它会导致read不重新解释输入中的\-sequences。
发布于 2013-06-24 12:46:07
DONE=false
until $DONE
do
read line || DONE=true
echo $line
done < blah.txt发布于 2014-05-08 03:56:52
只有一行答案:
IFS=$'\n'; for line in $(cat file.txt); do echo "$line" ; donehttps://stackoverflow.com/questions/17268113
复制相似问题