从命令行确定文件末尾是否没有 EOL

从命令行确定文件末尾是否没有 EOL

如果您打开一个文件,并且该文件的最后一行末尾vim没有“no” ,则编辑器会将其报告为.EOL[noeol]我怎样才能确定这个打开它在vim? (我可以发出命令来确定这一点吗?)

答案1

tail -c 1输出其输入的最后一个字符(更准确地说,最后一个字节)。

命令替换会去掉尾随的换行符,$(tail -c 1 <…)因此空的如果文件的最后一个字符是换行符。如果最后一个字符是空字节(在大多数 shell 中),它也为空,但文本文件没有空字节。

请记住,空文件不需要额外的换行符。

if [ ! -s "$filename" ]; then
  echo "$filename is empty"
elif [ -z "$(tail -c 1 <"$filename")" ]; then
  echo "$filename ends with a newline or with a null byte"
else
  echo "$filename does not end with a newline nor with a null byte"
fi

答案2

创建一个仅包含换行符的文件,然后将其与文件的最后一个字节进行比较:

printf '\n' > newline_only
tail -c 1 your_file | cmp -s newline_only -

我以前基本上cmp -scmp沉默的。退出状态0表示在 的最末尾有一个换行符your_file

如果your_file为空,则退出状态将为1。您可能想破例并参与0这种情况。如果是这样,前置cmp通过其标准输入获取的内容的换行符:

( printf '\n'; tail -c 1 your_file ) | cmp -s newline_only -
# or
cat newline_only your_file | tail -c 1 | cmp -s newline_only -
# or better
<your_file cat newline_only - | tail -c 1 | cmp -s newline_only -

your_file最后一个稍微好一些,因为如果不存在、无法读取等,它将返回非零退出状态。如果我是你,我会想要这个。尽管 ifyour_file实际上是一个目录 then cattail并且cmp将会运行,并且您可能会收到;0的投诉;cat或者可能不会,请看这个:目录何时停止作为文件读取?)。因此你可能想要一些额外的逻辑或选项(例如set -o pipefail在 Bash 中)。

笔记:

  • 在某些 shell 中,您可以使用进程替换来避免创建newline_only文件。它将是这样的:

    # e.g. in Bash
    < your_file cat <(printf '\n') - | tail -c 1 | cmp -s <(printf '\n') -
    
  • tail从管道读取无法查找。cat需要阅读全文your_file,然后tail才能完成其工作。tail -c 1 your_file或者<your_file tail -c 1可能足够聪明,能够向内寻求your_file。如果您测试一个或几个,这应该可以忽略不计小的文件虽然。

  • 这个其他解决方案可能会表现更好:它不创建文件;它不会通过管道进入tail;它不会产卵cmp;它使用的[是许多 shell 中的内置函数。

答案3

这其实跟没有什么关系vim。差不多就是你想要的

tail -c 1 file

获取文件的最后一个字符。

相关内容