sed将不需要的空格添加到文件末尾,使其无效

时间:2017-01-17 19:28:55

标签: bash macos unix sed

尝试使用sed替换文件内容,替换工作,但由于某种原因,我在结果输出文件的末尾获得额外的空格,导致文件在打开的应用程序中不可读/不可查看。

我的命令如下:

for file in *.example ; do LANG=C sed -i "" "s|https://foo.bar|http://foo.bar|g" "$file" ; done

我尝试过的事情没有成功:

  • 未将s / [...。] / g参数包装在引号中(导致命令失败)
  • 使用除|以外的分隔符例如/或_或%(没有区别)
  • 使用单引号而不是双引号(没有区别)
  • 逃离句号和冒号(没有区别)

编辑:此问题似乎与文件类型相关,因此我不再对解决方案感兴趣。感谢那些回复的人。

2 个答案:

答案 0 :(得分:1)

我建议更换

\foo.bar

通过

foo.bar

答案 1 :(得分:0)

事后看来:

BSD / macOS sed 从根本上不适合在二进制文件中进行替换,因为总是在每个输出命令中输出一个尾随\n(换行符)

相比之下, GNU sed没有此问题,因为它 - 值得称道 - 只有在输入时附加\n“行“也有一个。

请注意,换行符分隔线的概念并不真正适用于二进制输入:换行可能存在也可能不存在,并且可能存在大块数据。在最坏的情况下,整个输入将立即读取 [1]

您可以使用以下命令测试此行为:

sed -n 'p' <(printf 'x') | cat -et  # input printf 'x' has no trailing \n

输出x$表示添加了换行符($符号cat -et)(BSD Sed),而x表示它不是(GNU Sed) )。

因此,鉴于您使用的是macOS,可以使用Homebrew使用brew install gnu-sed安装GNU Sed,然后使用以下命令:

LANG=C gsed -i 's|https://foo.bar|http://foo.bar|g' *.example
  • Homebrew将GNU Sed安装为gsed,以便 macOS的股票(BSD)sed一起存在。

  • LANG=C(稍微更强大:LC_ALL=C)需要通过原样传递二进制输入的所有字节,而不会导致二进制字节无法识别为有效的问题< EM>字符的)。
    请注意,此方法将您限制为替换中的仅ASCII字符(除非您明确将字节值添加为转义序列)。

  • 请注意不同的,不兼容的-i语法,用于就地更新无备份 - (单独)选项 - 参数;请参阅我的this answer了解背景信息。

  • 注意如何在Sed脚本周围使用'...'(单引号),这通常是可取的,因为它避免了前面发生的shell扩展和Sed最终看到的内容之间的混淆。

[1]除了内存使用之外,在这里使用Sed的默认行解析行为是很好的,因为你的替换命令与换行符不匹配。但是,如果要将输入分解为NUL中的“行”(并且还在输出中使用NUL),则可以使用GNU Sed的-z选项。