如何删除sed创建的EOF空行

时间:2018-03-20 10:24:59

标签: bash macos awk sed scripting

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

你知道如何解决这个问题吗? (不使用截断,因为我不想在MacOS中安装其他软件)

谢谢!

1 个答案:

答案 0 :(得分:1)

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

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

这将删除最后一个<newline>。这不能由sed完成,下面的答案试图解释它。在How can I delete a newline if it is the last character in a file?

中可以找到更多可能性

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

根据sed posix standard

  

在默认操作中, 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 'foo\nbar' | sed 'p'                                                                                                                                                                                                
foo
foo

如果未被<newline>终止的行,则显然没有处理。否则,{@ 1}}会在任何输出处添加。

MacOS sed manual与posix有类似的间隔。

  

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

我没有测试,因为我没有mac。

GNU sed manual似乎对此事的看法略有不同:

  

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

     

当到达脚本结尾时,除非正在使用sed选项,否则模式空间的内容将打印到输出流,如果删除则添加回尾线。

这意味着以下内容:

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

示例:<newline>

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

012

这由Footnote 7解释:

  

实际上,如果 $ 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 打印的行没有终止换行符,那么它就是   但是,只要有更多文字,就会打印丢失的换行符   发送到相同的输出流,这给出了“最不期望的   惊讶“即使它没有像sed这样的命令   与sed -n p完全相同。

总结:根据posix standard,您最终会得到一个以cat结尾的输出文件,但它可能不是最后一行输入。根据{{​​3}},您的输出将以与输入文件末尾相同的数量终止。

问题是GNU&#39; <newline>真实的posix?