我正在使用sed来修改文本文件的第一部分。问题是sed会自动在文件末尾引入一个空行。
你知道如何解决这个问题吗? (不使用截断,因为我不想在MacOS中安装其他软件)
谢谢!
答案 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
会循环添加一行输入, 减少其终止<newline>
字符到模式空间。 如果模式中有<newline>
,则应跳过从输入读取 结束前一个周期的D
命令之前的空格。 sed实用程序 然后应按顺序应用其地址选择的所有命令 模式空间,直到命令开始下一个循环或退出。如果不 命令显式启动一个新循环,然后在脚本结束时 模式空间应复制到标准输出(-n
时除外 指定)并删除模式空间。 每当 模式空间被写入标准输出或命名文件sed
立即使用<newline>
。
这意味着两件事:
<newline>
终止,则不会处理该行。<newline>
终止,即作为命令周期结束或命令p
或P
发出的结果输出。示例: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?