如何删除 EOF 空行由 sed 创建



我正在使用sed来修改文本文件的第一部分。问题是 sed 会自动在文件末尾引入一个空行。

你知道怎么解决吗?(不使用截断,因为我不想在MacOS中安装其他软件)

谢谢!!

对您的问题的快速回答是将您的输出传输到另一个 cmd,例如awk

sed 'commands' file | awk '(NR>1){printf "%sn",l}{l=$0}END{printf "%s",l}'

这将删除最后一个<newline>。这不能通过sed来完成,下面的答案试图解释它。更多可能性可以在如何删除换行符中找到,如果换行符是文件中的最后一个字符?

为什么sed总是以<newline>结束?这个问题的答案取决于对标准的解释和您使用sed的实施。

根据sed标准:

在默认操作中,sed循环地附加一行输入, 减去其终止<newline>字符,进入模式空间。如果模式中有<newline>,则应跳过从输入读取 结束上一个循环的D命令之前的空格。sed 实用程序 然后,应按顺序应用其地址选择的所有命令 模式空间,直到命令开始下一个循环或退出。如果没有 命令显式启动一个新循环,然后在脚本结束时 模式空间应复制到标准输出(除非-n)并删除图案空间。每当 模式空间写入标准输出或命名文件,sed立即用<newline>紧随其后.

这意味着两件事:

  • 如果行未由<newline>终止,则不会处理该行。
  • 任何写入标准输出的内容都以<newline>终止,即由于命令周期结束或pP发出命令而导致的输出。

示例:sed (SunOS 5.10) SUNWcsu 11.10.0 rev=2005.01.21.15.53

$ echo -n foo | sed 'p'
$ echo -n 'foonbar' | sed 'p'                                                                                                                                                                                                
foo
foo

显然,如果没有被<newline>终止的行,则没有处理。否则,<newlines>将添加到任何输出中。

MacOSsed手册具有与posix类似的插入。

通常,sed循环复制一行输入,不包括其 终止换行符,进入 模式空间(除非在D函数之后还有剩余的东西)应用所有命令 对于选择该模式空间的地址,将模式空间复制到标准输出,追加追加 换行符,然后删除模式空间。

这没有经过测试,因为我没有 mac。

GNUsed手册似乎对这个问题的看法略有不同:

sed通过在每行输入上执行以下循环来操作: 首先,SED 从输入流中读取一行,删除任何尾随 换行符,并将其放置在模式空间中。然后命令是 执行;每个命令都可以有一个与之关联的地址:地址 是一种条件代码,只有在 在执行命令之前验证条件。

当到达脚本末尾时,除非正在使用-n选项,否则模式空间的内容将打印到输出流中,如果删除了尾随换行符,则会重新添加。

这意味着以下内容:

  • 所有行都已处理,全部或不由<newline>终止
  • 如果达到命令周期的末尾,则添加与最初删除的相同数量的<newline>

例 :sed (GNU sed) 4.2.2

在以下示例中,仅在p之后添加换行符,而不是在循环结束后添加换行符。(换行符在十六进制中012)

$ echo -n foo | hexdump -b
0000000 146 157 157                                                    
0000003
$ echo -n foo | sed --posix 'p' | hexdump -b
0000000 146 157 157 012 146 157 157                                    
0000007

脚注7对此进行了解释:

实际上,如果sed打印一行没有终止换行符,则 尽管如此,一旦有更多文本,就会打印缺少的换行符 发送到相同的输出流,这给出了"最不期望的" 惊喜",即使它不会发出类似sed -n p的命令 与cat完全相同。

结论:根据 posix 标准,您最终将始终得到一个以<newline>结尾的输出文件,但它可能不是输入的最后一行。根据 Gnu 手册,您的输出终止与输入文件末尾的输出量相同。

问题:GNU 的sed --posix是真正的 posix 吗?

最新更新