Bash Shell脚本读取缺少最后一行
我有一个。。。我希望对bashshell脚本有一些了解,这是一个奇怪的问题 我的团队正在编写一个脚本,该脚本遍历文件中的行并检查每行中的内容。我们有一个bug,当通过自动流程将不同的脚本排序在一起运行时,最后一行没有被看到 用于在文件中的行上迭代的代码(存储在Bash Shell脚本读取缺少最后一行,bash,process,Bash,Process,我有一个。。。我希望对bashshell脚本有一些了解,这是一个奇怪的问题 我的团队正在编写一个脚本,该脚本遍历文件中的行并检查每行中的内容。我们有一个bug,当通过自动流程将不同的脚本排序在一起运行时,最后一行没有被看到 用于在文件中的行上迭代的代码(存储在DATAFILE中的名称为 cat "$DATAFILE" | while read line 我们可以从命令行运行脚本,它可以看到文件中的每一行,包括最后一行。但是,当由自动化进程运行时(该进程运行在相关脚本之前生成数据文件的脚本),
DATAFILE
中的名称为
cat "$DATAFILE" | while read line
我们可以从命令行运行脚本,它可以看到文件中的每一行,包括最后一行。但是,当由自动化进程运行时(该进程运行在相关脚本之前生成数据文件的脚本),最后一行永远看不到
我们更新了代码,使用以下代码对行进行迭代,问题得到解决:
for line in `cat "$DATAFILE"`
注意:数据文件的末尾没有写新行
我的问题分为两部分…为什么原始代码看不到最后一行,为什么这一更改会产生不同
我只想我能想出为什么最后一行看不见的原因是:
- 前一个写入文件的进程依赖于进程结束以关闭文件描述符
- 问题脚本启动和打开文件的速度足够快,因此,尽管上一个进程已“结束”,但它还没有“关闭/清理”到系统自动关闭文件描述符的程度
如果您能深入了解这些问题,尤其是第一个问题,我们将不胜感激。C标准规定,文本文件必须以换行符结尾,否则最后一个换行符之后的数据可能无法正确读取 ISO/IEC 9899:2011§7.21.2 文本流是一个有序的字符序列,由行组成,每行 由零个或多个字符加上一个终止新行字符组成。是否 最后一行需要一个终止新行字符,该字符由实现定义。字符 可能必须在输入和输出时添加、更改或删除,以符合不同的要求 在宿主环境中表示文本的约定。因此,不需要有一个- 流中字符与外部字符之间的一种对应关系 表示。从文本流中读取的数据必须与数据进行比较 只有在以下情况下,才会将这些数据写入该流:数据仅由打印组成 字符和控制字符水平选项卡和新行;不允许使用新行字符 前面紧跟空格字符;最后一个字符是新行字符。 是否在新行字符之前写入空格字符 在定义读入实现时显示 我不会意外地在文件末尾缺少换行符,从而在
bash
(或任何Unix shell)中造成问题,但这似乎确实是一个重复出现的问题($
是此输出中的提示):
因此,他的技巧是:
while read line || [ -n "$line" ]; do echo $line; done < y
将适用于结尾没有换行符的文件(至少在我的机器上)
我仍然惊讶地发现,壳落在最后一段(它不能称为线,因为它没有以换行结束)但POSIX中可能有足够的理由这样做。显然,最好确保您的文本文件确实是以换行符结尾的文本文件。我在命令行中对此进行了测试
# create dummy file. last line doesn't end with newline
printf "%i\n%i\nNo-newline-here" >testing
使用第一个表单进行测试(管道到while循环)
这遗漏了最后一行,这是有意义的,因为read
只获取以换行结束的输入
使用第二个表单进行测试(命令替换) 这也是最后一行
read
仅当输入以换行符终止时才获取输入,这就是您错过最后一行的原因
另一方面,在第二种形式中
`cat testing`
扩展为
line1\nline2\n...lineM
它由shell使用IFS分隔为多个字段,因此
line1 line2 line3 ... lineM
这就是为什么你仍然得到最后一行
p/s:我不明白的是如何让第一个表单工作…根据,如果“检测到文件结尾或发生错误”,它应该返回非零状态。因为EOF在读取最后一行时被检测到,它设置$line
,然后返回一个错误状态,错误状态阻止循环在最后一行执行。解决方法很简单:如果读取命令成功,或者在$line
中读取了任何内容,则执行循环
while read line || [ -n "$line" ]; do
作为一种解决方法,在从文本文件读取之前,可以将换行符附加到该文件
echo "\n" >> $file_path
这将确保文件中以前的所有行都将被读取。使用sed匹配文件的最后一行,如果不存在,它将添加一个新行,并让它在线替换文件:
sed-i'-e'$a\'文件
代码来自此stackexchange
注意:我在-I'
中添加了空单引号,因为至少在OS X中,-I
使用了-e
作为备份文件的文件扩展名。我很乐意对原始帖子发表评论,但缺少50分。也许这会让我在这个帖子中获得一些分数,谢谢。我也有类似的问题。
我正在做一个文件的cat,将它传输到一个排序,然后将结果传输到一个“whilereadvar1var2var3”。
即:
cat$FILE |排序-k3 |读取计数IP名称时
做
“do”下的工作是一个if语句,该语句在$Name字段中识别不断变化的数据,并根据变化或无变化对$Count进行合计,或将合计行打印到报告中。
我还遇到了一个问题,即我无法将最后一行打印到报告中
`cat testing`
line1\nline2\n...lineM
line1 line2 line3 ... lineM
while read line || [ -n "$line" ]; do
echo "\n" >> $file_path
while IFS= read -r line; do
...
done <file
while IFS= read -r line || [ -n "$line" ]; do
echo "$line"
done <file
while IFS= read -r line; do
echo "$line"
done < <(grep "" file)