shell 脚本中没有换行符的最后一个命令行

lyl*_*klb 4 shell-script

为什么shell脚本(uptime下)的最后一个命令行可以在文件末尾没有换行符的情况下成功执行?

例如:

root@jcdb:/tmp# 
root@jcdb:/tmp# 
root@jcdb:/tmp# cat dp
date
pwd
uptimeroot@jcdb:/tmp# 
root@jcdb:/tmp# 
root@jcdb:/tmp# 
root@jcdb:/tmp# ./dp
Wed Jun  6 16:27:26 EAT 2018
/tmp
  4:27pm  up 1 day, 17:25,  2 users,  load average: 0.39, 0.40, 0.41
root@jcdb:/tmp# 
root@jcdb:/tmp#
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 5

当 shell 读取 shell 脚本时,即使没有终止换行符,它的扫描码也会接受脚本末尾的最后一个单词。

这是POSIX 标准中关于 shell 如何识别其输入中的标记的第一条规则的影响:

如果识别到输入结束,则应分隔当前标记(如果有)。

它说当前标记在此处被分隔的事实意味着脚本中的最后一个单词以及该未终止行的其余部分将被接受为解释器的输入,而不是导致错误或将 shell 放入一个未定义的状态。


在评论中,引用了vi编辑。标准vi编辑器可以编辑最后一行没有以换行符终止的文件。但是,在将缓冲区的最后一行写入文件时,它将用换行符终止缓冲区的最后一行(除了在保存空文件时,在这种情况下明确不允许添加换行符)。对于标准ex编辑器也是如此:

输入文件

输入文件应为文本文件或将是文本文件的文件,除了{LINE_MAX}-1长度不超过字节且不包含NUL字符的不完整的最后一行。默认情况下,任何不完整的最后一行都应视为尾随<newline>. ex实现可以选择性地允许编辑其他形式的文件。

vim编辑器有一个设置eol,它决定是否应该保留未终止的最后一行或没有。默认行为是终止最后一行。见:help eolvim

标准ed编辑器的输入应该是一个文本文件,这意味着如果编辑的文件的最后一行未正确终止(这使其不是文本文件)在技术上未指定会发生什么。在 OpenBSD 上,ed当打开一个未终止的文本文件时,编辑器会说“附加换行符”。

输入文件

输入文件应为文本文件。