awk

awk

例如,我有一个大(~180MB)的 xml 文件,其中包含一些错误的字符

<Data ss:Type="String">7402953^@</Data>

^@部件应被移除。这项工作应该完成

sed -i 's/\^@//g' /tmp/large.xml

但由于某种未知的原因,如果字符串位于我的大 xml 文件中,它就无法按预期工作。如果文件大小只有几 KB,则sed可以正常工作。

它看起来像一个错误,但我认为不可能,因为任务非常明显。我做错了什么吗?

答案1

从你的问题来看(因为没有例子),我想说^@在大文件中实际上并不是两个字符(^@),而是那些不可打印的字符之一。

Ctrl + v您可以使用+在终端中输入该不可打印的字符Ctrl + 2
用它来sed代替字符^@应该没问题。

还要删除转义序列,因为不可打印字符不需要它。

答案2

awk

如果使用的解决方案awk可以接受,这将删除所有不可打印的字符。

这适用于 GNU awk (Linux) 和 BSD awk (Mac)。

awk '{ gsub(/[^[:print:][:blank:]]/,"",$0) ; print $0 }' input.xml > output.xml
  • gsub(/[^[:print:][:blank:]]/,"",$0)
    从输入的每一行中删除任何不需要的字符。
    • [:print:]
      任何可打印字符。
    • [:blank:]
      空格或制表符。
    • [^[:print:][:blank:]]
      不包含在这两个类别中的任何角色。
  • print $0
    打印输入的每一行。
  • > output.xml
    将输出保存到文件中,而不是将其打印到屏幕上。

用更少的击键来做同样的事情(只是阅读起来有点困难):

awk '{gsub(/[^[:print:][:blank:]]/,"")}1' input.xml > output.xml
  • 如果您正在检查整行,则不需要指定,$0(整行输入) 。gsub
  • 最后的意思1是“现在对每一行执行默认操作(即打印)”。

相关内容