Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash Shell脚本读取缺少最后一行_Bash_Process - Fatal编程技术网

Bash Shell脚本读取缺少最后一行

Bash Shell脚本读取缺少最后一行,bash,process,Bash,Process,我有一个。。。我希望对bashshell脚本有一些了解,这是一个奇怪的问题 我的团队正在编写一个脚本,该脚本遍历文件中的行并检查每行中的内容。我们有一个bug,当通过自动流程将不同的脚本排序在一起运行时,最后一行没有被看到 用于在文件中的行上迭代的代码(存储在DATAFILE中的名称为 cat "$DATAFILE" | while read line 我们可以从命令行运行脚本,它可以看到文件中的每一行,包括最后一行。但是,当由自动化进程运行时(该进程运行在相关脚本之前生成数据文件的脚本),

我有一个。。。我希望对bashshell脚本有一些了解,这是一个奇怪的问题

我的团队正在编写一个脚本,该脚本遍历文件中的行并检查每行中的内容。我们有一个bug,当通过自动流程将不同的脚本排序在一起运行时,最后一行没有被看到

用于在文件中的行上迭代的代码(存储在
DATAFILE
中的名称为

cat "$DATAFILE" | while read line 
我们可以从命令行运行脚本,它可以看到文件中的每一行,包括最后一行。但是,当由自动化进程运行时(该进程运行在相关脚本之前生成数据文件的脚本),最后一行永远看不到

我们更新了代码,使用以下代码对行进行迭代,问题得到解决:

for line in `cat "$DATAFILE"` 
注意:数据文件的末尾没有写新行

我的问题分为两部分…为什么原始代码看不到最后一行,为什么这一更改会产生不同

我只想我能想出为什么最后一行看不见的原因是:

  • 前一个写入文件的进程依赖于进程结束以关闭文件描述符
  • 问题脚本启动和打开文件的速度足够快,因此,尽管上一个进程已“结束”,但它还没有“关闭/清理”到系统自动关闭文件描述符的程度
也就是说,如果一个shell脚本中有两个命令,那么在脚本运行第二个命令时,第一个命令应该完全关闭


如果您能深入了解这些问题,尤其是第一个问题,我们将不胜感激。

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)