【问题标题】:Remove junk characters from a utf-8 file in Unix从 Unix 中的 utf-8 文件中删除垃圾字符
【发布时间】:2017-06-01 16:20:36
【问题描述】:

我在一个文件中获取了垃圾字符(<9f><9d><9d> 等)、CNTRL 字符(^Z^M 等)和NULL 字符(^@) .但是,我能够从文件中删除 CNTRLNULL 字符,但无法消除垃圾字符。谁能建议一种方法来删除这些垃圾字符?

正在使用以下命令删除控制字符:

sed 's/\x1a//g;s/\xef\xbf\xbd//g'

使用以下命令删除空字符

tr -d '\000'

另外,请建议一个命令来删除所有上述 3 种类型的 garbal 字符。

提前致谢

【问题讨论】:

  • Dos2Unix 也无法正常工作。错误状态“转换文件时出现问题”
  • 文件的编码是什么?您可以将文件粘贴到 pastebin.com 上吗?
  • 文件编码为utf-8。抱歉,我无法放置文件。

标签: shell unix unicode strip null-character


【解决方案1】:

去除“不寻常”的 unicode 字符

在您提到的 cmets 中,您希望在保留希腊字符的同时屏蔽控制字符,因此下面使用 tr 的解决方案不适合。一种解决方案是 sed,它提供 unicode 支持,并且它们的 [[:alpha:]] 类也匹配 ascii 之外的字母字符。您首先需要设置LC_CTYPE 以指定哪些字符都属于[[:alpha:]] 范围。对于带元音变音的德语,例如

LC_CTYPE=de_DE.UTF-8

然后您可以使用sed 删除所有不是字母或标点符号的内容:

sed 's/[^[:alpha:];\ -@]//g' < junk.txt

\ -@ 的作用:它匹配空格和 @ 之间的 ascii 范围内的所有字符(参见 ascii table。Sed 有一个 [[:punct:]] 类,但不幸的是这也匹配了很多垃圾,所以 @987654335需要@。

您可能需要玩一下 LC_CTYPE,将其设置为 utf-8 只有我可以匹配希腊字符,但不能匹配日语。

如果你只关心ascii

如果您只关心常规 ascii 字符,您可以使用 tr:首先将文件转换为“每个字符一个字节”编码,因为 tr 不理解多字节字符,例如使用iconv

然后,我建议您使用白名单方法(与您在问题中使用的黑名单方法相反),因为与您要过滤掉的内容相比,说明您想要保留的内容要容易得多。

这个命令应该可以做到:

iconv -c -f utf-8 -t latin1 < junk.txt | tr -cd '\11\12\40-\176'

这一行..

  • 转换为 latin1(每个字符一个字节)并忽略代码点 127 以上的所有字符(这是特殊字符,但请注意,这也会去除您可能想要保留的语言中的变音符号或特殊字符之类的东西! )
  • 删除此白名单之外的所有字符:\11\12\40-\176。那里的数字是八进制的。看看例如this ascii table\11tab\12 是回车。 \40-\176 是所有通常被认为是“正常”的字符

【讨论】:

  • 感谢您的建议。我已经使用过这个 tr -cd '\11\12\40-\176' 命令。所有的垃圾字符已被删除。但是,我也失去了一些希腊字符。我需要那些希腊字符
  • 而且,如果我使用 iconv 将文件从 utf-8 转换为 us-latin,我将丢失所有 Unicode 字符,例如日本数据、希腊数据
  • @user2975559 我扩展了我的答案以匹配 ascii 集之外的 unicode 字符,你能检查一下这是否能解决你的问题吗?