我有几个非常大的XML文件,我试图找到包含非ascii字符的行。我试过以下几种方法:
grep -e "[\x{00FF}-\x{FFFF}]" file.xml
但是这将返回文件中的每一行,而不管该行是否包含指定范围内的字符。
是我的语法错误还是我做错了什么?我也试过:
egrep "[\x{00FF}-\x{FFFF}]" file.xml
(在模式周围使用单引号和双引号)。
我有几个非常大的XML文件,我试图找到包含非ascii字符的行。我试过以下几种方法:
grep -e "[\x{00FF}-\x{FFFF}]" file.xml
但是这将返回文件中的每一行,而不管该行是否包含指定范围内的字符。
是我的语法错误还是我做错了什么?我也试过:
egrep "[\x{00FF}-\x{FFFF}]" file.xml
(在模式周围使用单引号和双引号)。
当前回答
查找所有非ascii字符会给人留下这样的印象:要么查找unicode字符串,要么打算单独剥离这些字符。
对于前者,可以尝试其中一个(变量文件用于自动化):
file=file.txt ; LC_ALL=C grep -Piao '[\x80-\xFF\x20]{7,}' $file | iconv -f $(uchardet $file) -t utf-8
file=file.txt ; pcregrep -iao '[\x80-\xFF\x20]{7,}' $file | iconv -f $(uchardet $file) -t utf-8
file=file.txt ; pcregrep -iao '[^\x00-\x19\x21-\x7F]{7,}' $file | iconv -f $(uchardet $file) -t utf-8
如前面的答案所述,如果没有LC_ALL=C, Vanilla grep将无法正常工作。
ASCII范围是x00-x7F,空格是x20,因为字符串有空格,所以负范围省略了它。
非ascii范围是x80-xFF,因为字符串有空格,所以正范围加上它。
String假定在范围内至少有7个连续字符。{7}。
对于shell可读输出,uchardet $file返回文件编码的猜测值,该值被传递给iconv进行自动插值。
其他回答
不像上面大多数解决方案那样对非ASCII字符的字节范围进行假设,在我看来,明确ASCII字符的实际字节范围会稍微好一些。
所以第一个解决方案是:
grep --color='auto' -P -n '[^\x00-\x7F]' file.xml
(基本上greps十六进制ASCII范围以外的任何字符:从\x00到\x7F)
在Mountain Lion上,这将无法工作(由于BSD grep中缺乏PCRE支持),但通过Homebrew安装PCRE,以下将同样工作:
pcregrep --color='auto' -n '[^\x00-\x7F]' file.xml
大家能想到什么优点或缺点吗?
下面的代码工作:
find /tmp | perl -ne 'print if /[^[:ascii:]]/'
将/tmp替换为要搜索的目录名。
这个方法应该适用于任何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
以下是我的工作:
grep -P "[\x80-\xFF]" file.xml
非ascii字符从0x80开始,在查看字节时转到0xFF。Grep(和家族)不做Unicode处理,将多字节字符合并为一个实体,以便进行正则表达式匹配。我的grep中的-P选项允许在字符类中使用\xdd转义来实现您想要的效果。
这是我发现的另一个变体,它与grep搜索[\x80-\xFF]的结果完全不同。也许它会有用的人找到额外的非ascii字符:
grep -颜色= '汽车' - p - n”[^ [ascii:]]”myfile.txt
注意:我的电脑的grep (Mac)没有-P选项,所以我brew install grep,并使用ggrep而不是grep开始上面的调用。