我如何在UNIX中对所有非A​​SCII字符进行grep

我有几个非常大的XML文件,我试图find包含非ASCII字符的行。 我已经尝试了以下内容:

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

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

我的语法错了吗?还是我在做其他的错误? 我也试过:

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

(包含模式的单引号和双引号)。

你可以使用这个命令:

 grep --color='auto' -P -n "[\x80-\xFF]" file.xml 

这将给你的行号,并将突出显示非ASCII字符红色。

在一些系统中,根据你的设置,上面的将不起作用,所以你可以通过grep来反转

 grep --color='auto' -P -n "[^\x00-\x7F]" file.xml 

还要注意,重要的一点是-P标志等同于--perl-regexp :所以它将把你的模式解释成一个Perl正则expression式。 它也是这样说的

这是高度实验性的,grep -P可能会警告未实现的function。

与上面大多数解决scheme一样,不是假定非ASCII字符的字节范围,而是稍微好一点的IMO来清楚地说明ASCII字符的实际字节范围。

所以第一个解决scheme就是:

 grep --color='auto' -P -n '[^\x00-\x7F]' file.xml 

(基本上这个hexASCII范围之外的任何字符都是grep:从\ x00到\ x7F)

在Mountain Lion上, 由于在BSD grep中缺lessPCRE支持,所以无法工作,但是通过Homebrew安装pcre ,下面的工作也是一样的:

 pcregrep --color='auto' -n '[^\x00-\x7F]' file.xml 

任何人都可以想到的优点或缺点?

以下为我工作:

 grep -P "[\x80-\xFF]" file.xml 

非ASCII字符从0x80开始,在查看字节时转到0xFF。 grep(和家庭)不做Unicode处理合并多字节字符为一个单一的实体正则expression式匹配,你似乎想要的。 grep中的-P选项允许在字符类中使用\xdd转义来完成你想要的。

在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可以完全避免依赖于语言环境的效果。

这里是另一个我发现的变体,它在接受的答案中产生了与grepsearch[\x80-\xFF] 完全不同的结果。 也许有人find其他的非ascii字符是有用的:

grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt

注意:我的电脑的grep(一个Mac)没有-P选项,所以我做了brew install grep并用ggrep而不是grep来启动上面的调用。

以下代码工作:

 find /tmp | perl -ne 'print if /[^[:ascii:]]/' 

/tmpreplace为您要search的目录的名称。

奇怪的是,我今天不得不这样做! 我结束了使用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 }' '{}' \; 

知道如何search一个Unicode字符可能很有趣。 这个命令可以帮助。 你只需要知道UTF8的代码

 grep -v $'\u200d' 

search不可打印的字符。

我同意上面埋藏在评论中的哈维 ,通常search非打印字符更有用,或者当你真的认为不可打印时,很容易想到非ASCII。 哈维build议“使用这个:”[^ \ n – 〜]“。为DOS文本文件添加\ r,转换为”[^ \ x0A \ x020- \ x07E]“,为CR添加\ x0D”

另外,当search不可打印的字符时,将-c(显示匹配的模式数)显示为grep非常有用,因为匹配的string可能会弄乱terminal。

我发现添加范围0-8和0x0e-0x1f(到0x80-0xff范围)是一个有用的模式。 这排除了TAB,CR和LF以及一两个不常见的可打印字符。 所以恕我直言,一个相当有用的(虽然粗糙)grep模式是这样的:

 grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" * 

分解:

 \x00-\x08 - non-printable control chars 0 - 7 decimal \x0E-\x1F - more non-printable control chars 14 - 31 decimal \x80-1xFF - non-printable chars > 128 decimal -c - print count of matching lines instead of lines -P - perl style regexps Instead of -c you may prefer to use -n (and optionally -b) or -l -n, --line-number -b, --byte-offset -l, --files-with-matches 

例如使用find的实际例子来grep当前目录下的所有文件:

 find . -type f -exec grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" {} + 

你可能希望有时调整grep。 例如某些可打印文件中使用的BS(0x08 – 退格)char或排除VT(0x0B – 垂直制表符)。 在某些情况下,BEL(0x07)和ESC(0x1B)字符也可以被认为是可打印的。

 Non-Printable ASCII Chars ** marks PRINTABLE but CONTROL chars that is useful to exclude sometimes Dec Hex Ctrl Char description Dec Hex Ctrl Char description 0 00 ^@ NULL 16 10 ^P DATA LINK ESCAPE (DLE) 1 01 ^A START OF HEADING (SOH) 17 11 ^Q DEVICE CONTROL 1 (DC1) 2 02 ^B START OF TEXT (STX) 18 12 ^R DEVICE CONTROL 2 (DC2) 3 03 ^C END OF TEXT (ETX) 19 13 ^S DEVICE CONTROL 3 (DC3) 4 04 ^D END OF TRANSMISSION (EOT) 20 14 ^T DEVICE CONTROL 4 (DC4) 5 05 ^E END OF QUERY (ENQ) 21 15 ^U NEGATIVE ACKNOWLEDGEMENT (NAK) 6 06 ^F ACKNOWLEDGE (ACK) 22 16 ^V SYNCHRONIZE (SYN) 7 07 ^G BEEP (BEL) 23 17 ^W END OF TRANSMISSION BLOCK (ETB) 8 08 ^H BACKSPACE (BS)** 24 18 ^X CANCEL (CAN) 9 09 ^I HORIZONTAL TAB (HT)** 25 19 ^Y END OF MEDIUM (EM) 10 0A ^J LINE FEED (LF)** 26 1A ^Z SUBSTITUTE (SUB) 11 0B ^K VERTICAL TAB (VT)** 27 1B ^[ ESCAPE (ESC) 12 0C ^L FF (FORM FEED)** 28 1C ^\ FILE SEPARATOR (FS) RIGHT ARROW 13 0D ^M CR (CARRIAGE RETURN)** 29 1D ^] GROUP SEPARATOR (GS) LEFT ARROW 14 0E ^N SO (SHIFT OUT) 30 1E ^^ RECORD SEPARATOR (RS) UP ARROW 15 0F ^O SI (SHIFT IN) 31 1F ^_ UNIT SEPARATOR (US) DOWN ARROW