shell 脚本没有从 sysin 读取最后一行

shell script does not read last line from sysin

我尝试从 sysin 获取一些数据,这是我的问题:如果数据是从文件定向的,则不会读取最后一行。 文本文件示例:

line1
line2
line3

我的代码:

#!/bin/bash
while read line
do
  echo "$line"
done

并输出:

$ ./test.sh < data.txt
line1
line2

如果我在文件末尾写下空字符串输出正确。但我不喜欢它。 如何解决这个问题?

我敢打赌 data.txt 缺少尾随换行符,请尝试检查

od -xa data.txt

看最后:

$ od -xa data.txt
0000000    696c    656e    0a31    696c    656e    0a32    696c    656e
          l   i   n   e   1  nl   l   i   n   e   2  nl   l   i   n   e
0000020    0033
          3
0000021

如果你看到上面的内容,你就漏掉了换行符。

$ od -xa data-with-nl.txt
0000000    696c    656e    0a31    696c    656e    0a32    696c    656e
          l   i   n   e   1  nl   l   i   n   e   2  nl   l   i   n   e
0000020    0a33
          3  nl
0000022

如果缺少尾随换行符,某些 shell 也会显示 % 符号,请尝试:

$ cat data.txt
line1
line2
line3%
$

如果你最终需要在没有EOL的情况下拼命读取文件,那么你可以检查返回的字符串是否为空而不是检查read退出状态:

#!/bin/bash
while true; do
  line=''
  read line
  if [ -z "$line" ]; then
    break
  fi
  echo "$line"
done

这个的成语是:

while read -r line || [[ $line ]]; do
  : process "$line"
done

因此,我们继续循环 while either:

  • 我们读取了一行有效的文本(需要换行符)
  • 我们进行了部分读取(导致非零退出状态,但使变量非空)。