我有几个非常大的XML文件,我试图找到包含非ascii字符的行。我试过以下几种方法:

grep -e "[\x{00FF}-\x{FFFF}]" file.xml

但是这将返回文件中的每一行,而不管该行是否包含指定范围内的字符。

是我的语法错误还是我做错了什么?我也试过:

egrep "[\x{00FF}-\x{FFFF}]" file.xml 

(在模式周围使用单引号和双引号)。


当前回答

知道如何搜索一个unicode字符可能会很有趣。该命令可以提供帮助。你只需要知道UTF8的代码

grep -v $'\u200d'

其他回答

这个方法应该适用于任何posix兼容的awk和iconv版本。 我们还可以利用file和tr。

curl当然不是POSIX。

上面的解决方案在某些情况下可能更好,但它们似乎依赖于GNU/Linux实现或其他工具。

只是以某种方式获得一个示例文件:

$ curl他们http://gutenberg.org/files/84/84-0.txt

$ file 84-0.txt

84-0.txt: UTF-8 Unicode(带BOM)文本,带有CRLF行终止符

搜索UTF-8字符:

$ awk '/[\x80-\xFF]/ { print }' 84-0.txt

或非ascii

$ awk '/[^[:ascii:]]/ {print}' 84-0.txt

将UTF-8转换为ASCII,删除有问题的字符(包括BOM,无论如何不应该是UTF-8):

$ iconv -c -t ASCII 84-0.txt

检查:

$ file 84-ascii.txt

84-ascii.txt: ASCII文本,带有CRLF行结束符

调整它以删除DOS行结束符/ ^M(“CRLF行终止符”):

$ tr -d '\015' < 84-ascii.txt > 84-tweak .txt &&文件84-tweak .txt

84-tweak .txt: ASCII文本

此方法会丢弃它无法处理的任何“坏”字符,因此您可能需要对输出进行消毒/验证。YMMV

在perl中

perl -ane '{ if(m/[[:^ascii:]]/) { print  } }' fileName > newFile

最简单的方法是定义一个非ascii字符…作为非ASCII字符的字符。

LC_ALL=C grep '[^ -~]' file.xml

如果需要,在^后面添加一个制表符。

设置LC_COLLATE=C可以避免在许多地区中出现关于字符范围含义的令人讨厌的意外。必须设置LC_CTYPE=C以匹配单字节字符-否则该命令将错过当前编码中的无效字节序列。设置LC_ALL=C可以完全避免语言环境相关的影响。

奇怪的是,我今天不得不这么做!我最终使用了Perl,因为我无法让grep/egrep工作(甚至在-P模式下)。喜欢的东西:

cat blah | perl -en '/\xCA\xFE\xBA\xBE/ && print "found"'

对于unicode字符(比如下面例子中的\u2212)使用:

find . ... -exec perl -CA -e '$ARGV = @ARGV[0]; open IN, $ARGV; binmode(IN, ":utf8"); binmode(STDOUT, ":utf8"); while (<IN>) { next unless /\N{U+2212}/; print "$ARGV: $&: $_"; exit }' '{}' \;

知道如何搜索一个unicode字符可能会很有趣。该命令可以提供帮助。你只需要知道UTF8的代码

grep -v $'\u200d'