首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用shell脚本中的read命令逐行读取输入文件会跳过最后一行

使用shell脚本中的read命令逐行读取输入文件会跳过最后一行
EN

Stack Overflow用户
提问于 2013-06-24 12:38:38
回答 4查看 117.6K关注 0票数 20

我通常使用read命令逐行将输入文件读入shell脚本。如果在输入文件blah.txt的最后一行末尾没有插入新行,则下面这样的示例代码会产生错误的结果。

代码语言:javascript
复制
#!/bin/sh

while read line
do
echo $line
done <blah.txt

因此,如果输入文件读取如下内容-

代码语言:javascript
复制
One 
Two
Three
Four

并且我没有在四次之后按回车键,脚本无法读取最后一行,并打印

代码语言:javascript
复制
One
Two
Three

如果我在四个之后多留一个空行,比如,

代码语言:javascript
复制
One 
Two
Three
Four
//blank line

输出将打印所有行,包括四行。但是,当我使用cat命令读取行时,情况并非如此;打印包括最后一行在内的所有行,而不必在末尾添加额外的空行。

有人知道为什么会发生这种情况吗?我创建的脚本主要由其他人运行,所以他们没有必要在每个输入文件的末尾添加额外的空行。

多年以来,我一直在尝试解决这个问题;如果您有任何解决方案,我将不胜感激(当然,cat命令就是其中之一,但我想知道read不能正常工作的原因)。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-06-24 12:46:36

read将一直读取,直到找到换行符或文件末尾,如果遇到文件末尾,则返回非零退出代码。所以它很有可能同时读取一行并返回一个非零的退出代码。

因此,如果输入可能未以换行符终止,则以下代码是不安全的:

代码语言:javascript
复制
while read LINE; do
  # do something with LINE
done

因为while的主体不会在最后一行执行。

从技术上讲,不以换行符结尾的文件不是文本文件,文本工具在这样的文件上可能会以奇怪的方式失败。然而,我总是不愿意回到那个解释上来。

解决这个问题的一种方法是测试读取的内容是否是非空的(-n):

代码语言:javascript
复制
while read -r LINE || [[ -n $LINE ]]; do
  # do something with LINE
done

其他解决方案包括使用mapfile将文件读取到一个数组中,通过某个工具(例如,grep .,如果您不想处理空行,则可以保证正确终止最后一行)通过管道传输文件,或者使用像awk这样的工具进行迭代处理(这通常是我的首选)。

请注意,在read内置中几乎肯定需要-r;它会导致read不重新解释输入中的\-sequences。

票数 21
EN

Stack Overflow用户

发布于 2013-06-24 12:46:07

代码语言:javascript
复制
DONE=false
until $DONE
do
  read line || DONE=true
  echo $line
done < blah.txt

How to use while read (Bash) to read the last line in a file if there’s no newline at the end of the file?

票数 8
EN

Stack Overflow用户

发布于 2014-05-08 03:56:52

只有一行答案:

代码语言:javascript
复制
IFS=$'\n'; for line in $(cat file.txt); do echo "$line" ; done
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17268113

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档