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

标签 bash parsing shell file-io

我通常使用 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 无法正常工作的原因)。

最佳答案

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(通常是我的偏好)之类的工具进行迭代处理。

请注意 -r 几乎肯定在 read 内置函数中是必需的;它导致 read 不重新解释输入中的 \ 序列。

关于bash - 在 shell 脚本中使用 read 命令逐行读取输入文件会跳过最后一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17268113/

相关文章:

bash - 为什么正则表达式中少一个空格会使我的 sed 变得奇怪?

bash - 使用grep提取html文件的标题

java - Jsoup 解析非空替代文本

c# - 如何使用 Linq 解析 XML 文件 - 后代

c++ - 受模式约束的最长公共(public)子串

bash - 如何将文件的内容与列的最后一个数字的增量连接起来

linux - 在适用于 Linux 的 Windows 子系统中安装 Windows 共享

bash 脚本错误让 : -: syntax error: operand expected (error token is "-")

bash - 在 unix shell 脚本中迭代一系列日期

linux - Bash Shell 语法错误完成 < $vid'