在bash中测试“ tail -c 1”

时间:2019-05-10 15:20:57

标签: bash tail

Linux - check if there is an empty line at the end of a file中,有些帖子使用[[ ]]==来比较字符。

我想编写一个单行命令来检测EOF中是否没有换行符,而我遇到了这个小问题。

echo的输出中,末尾有\n

$ echo echo | od -c           
0000000   e   c   h   o  \n
0000005
$ echo -n echo | od -c           
0000000   e   c   h   o
0000004

如果我将[[ ]]==放在一起,那么我不会得到预期的输出。

$ [[ `echo echo | tail -c1` == "\n" ]] && echo true
$ [[ `echo echo | tail -c1` != "\n" ]] && echo true
true
$ [[ `echo -n echo | tail -c1` != "\n" ]] && echo true
true

od -c所示,echo echo | tail -c1的输出为\n,而[[ "\n" == "\n" ]] && true将返回true,所以我希望第一个命令给出{{ 1}}。但是,为什么将它评估为空字符串?

感谢阅读!

2 个答案:

答案 0 :(得分:2)

Bash Reference Manual中已明确指出:

  

Bash通过在子shell环境中执行命令并将命令替换替换为命令的标准输出,并删除所有尾随换行符来执行扩展。

打开-x标志以查看清楚的情况:

$ set -x
$ [[ `echo echo | tail -c 1` == '\n' ]]
++ tail -c 1
++ echo echo
+ [[ '' == \\\n ]]
$
$ echo "$(echo)"
++ echo
+ echo ''

此外,即使未修剪尾随的换行符,您的比较也不会返回true,因为'\n'不是换行符,而实际上是反斜杠,后跟字母n。您应该使用$'\n'来获取实际的换行符。

答案 1 :(得分:1)

对于解决方案,您可以使用以下内容:

$ printf 'test\n' | perl -0777ne'exit(/\n\z/?0:1)' || echo "Missing line feed" >&2

$ printf 'test'   | perl -0777ne'exit(/\n\z/?0:1)' || echo "Missing line feed" >&2
Missing line feed

$ printf 'test\n' | perl -0777ne'die("Missing line feed\n") if !/\n\z/'

$ printf 'test'   | perl -0777ne'die("Missing line feed\n") if !/\n\z/'
Missing line feed