我有几个非常大的XML文件,我正在尝试查找包含非ASCII字符的行。我尝试了以下内容:
grep -e "[\x{00FF}-\x{FFFF}]" file.xml
但是这会返回文件中的每一行,无论该行是否包含指定范围内的字符。
我的语法错误还是我做错了什么?我也试过了:
egrep "[\x{00FF}-\x{FFFF}]" file.xml
(模式周围有单引号和双引号)。
答案 0 :(得分:439)
您可以使用命令:
grep --color='auto' -P -n "[\x80-\xFF]" file.xml
这将为您提供行号,并以红色突出显示非ascii字符。
在某些系统中,根据您的设置,以上操作不起作用,因此您可以通过反向grep
grep --color='auto' -P -n "[^\x00-\x7F]" file.xml
另请注意,重要位是-P
标志,等于--perl-regexp
:因此它会将您的模式解释为Perl正则表达式。它还说
这是高度实验性的,grep -P可能会警告未实现 特征
答案 1 :(得分:108)
与上述大多数解决方案一样,不是对非ASCII字符的字节范围进行假设,而是明确更好地了解ASCII字符的实际字节范围。
所以第一个解决方案就是:
grep --color='auto' -P -n '[^\x00-\x7F]' file.xml
(基本上对于十六进制ASCII范围之外的任何字符进行greps:从\ x00到\ x7F)
在Mountain Lion上无法正常工作(由于缺少BSD grep中的PCRE支持),但是通过Homebrew安装了pcre
,以下内容也可以正常工作:
pcregrep --color='auto' -n '[^\x00-\x7F]' file.xml
任何人都可以想到的任何利弊?
答案 2 :(得分:66)
以下适用于我:
grep -P "[\x80-\xFF]" file.xml
非ASCII字符从0x80开始,在查看字节时转到0xFF。 Grep(和系列)不进行Unicode处理,将多字节字符合并到单个实体中,以便进行正则表达式匹配。我的grep中的-P
选项允许在字符类中使用\xdd
转义来完成你想要的。
答案 3 :(得分:47)
在perl
perl -ane '{ if(m/[[:^ascii:]]/) { print } }' fileName > newFile
答案 4 :(得分:38)
简单的方法是将非ASCII字符定义为不是ASCII字符的字符。
LC_ALL=C grep '[^ -~]' file.xml
如有必要,请在^
之后添加标签。
设置LC_COLLATE=C
避免了许多语言环境中字符范围含义的令人讨厌的意外。设置LC_CTYPE=C
是匹配单字节字符所必需的 - 否则命令将错过当前编码中的无效字节序列。设置LC_ALL=C
完全避免了与语言环境相关的影响。
答案 5 :(得分:21)
我发现这是另一个变体,它在接受的答案中使用grep搜索[\x80-\xFF]
生成完全不同的结果。也许有人找到其他非ascii字符会很有用:
grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt
注意:我的计算机的grep(Mac)没有-P
选项,因此我执行了brew install grep
并使用ggrep
而不是grep
开始了上述调用。< / p>
答案 6 :(得分:8)
以下代码有效:
find /tmp | perl -ne 'print if /[^[:ascii:]]/'
将/tmp
替换为您要搜索的目录的名称。
答案 7 :(得分:4)
搜索不可打印的字符。
我同意上面隐藏在评论中的Harvey,搜索不可打印的字符通常更有用,或者当你真的应该考虑不可打印时很容易想到非ASCII。 Harvey建议“使用这个:”[^ \ n - 〜]“。为DOS文本文件添加\ r \ n。转换为”[^ \ x0A \ x020- \ x07E]“并为CR添加\ x0D”
此外,在搜索不可打印的字符时,向grep添加-c(显示匹配的模式数)非常有用,因为匹配的字符串可能会使终端陷入困境。
我发现添加范围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
E.g。使用find的实际例子grep当前目录下的所有文件:
find . -type f -exec grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" {} +
您可能希望有时调整grep。例如BS(0x08 - 退格)字符在某些可打印文件中使用或排除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
答案 8 :(得分:1)
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 }' '{}' \;
答案 9 :(得分:0)
知道如何搜索一个unicode字符可能很有趣。这个命令可以帮助你。您只需要知道UTF8中的代码
grep -v $'\u200d'
答案 10 :(得分:0)
查找所有非ASCII字符给人的印象是,要么正在寻找Unicode字符串,要么打算单独剥离所述字符。
对于前者,请尝试以下方法之一(变量file
用于自动化):
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,香草grep无法正常工作。
ASCII范围为x00-x7F
,空格为x20
,因为字符串中的空格带有负范围,所以忽略它。
非ASCII范围是x80-xFF
,因为字符串之间有空格,正数范围会将其相加。
假定字符串在该范围内至少为7个连续字符。 {7,}
。
对于外壳可读的输出,uchardet $file
返回对文件编码的猜测,并传递给iconv以进行自动插值。
答案 11 :(得分:0)
如果您尝试抓取/grep UTF8 兼容的多字节字符,请使用:
( [\302-\337][\200-\277]|
[\340][\240-\277][\200-\277]|
[\355][\200-\237][\200-\277]|
[\341-\354\356-\357][\200-\277][\200-\277]|
[\360][\220-\277][\200-\277][\200-\277]|
[\361-\363][\200-\277][\200-\277][\200-\277]|
[\364][\200-\217][\200-\277][\200-\277] )
* please delete all newlines, spaces, or tabs in between (..)
* feel free to use bracket ranges {1,3} etc to optimize
the redundant listings of [\200-\277]. but don't change that
[\200-\277]+, as that might result in invalid encodings
due to either insufficient or too many continuation bytes
* although some historical UTF-8 references considers 5- and
6-byte encodings to be valid, as of Unicode 13 they only
consider up to 4-bytes
我已经针对随机二进制文件测试了这个字符串,它会报告与 gnu-wc 相同的多字节字符数。
如果您需要完整的 UTF8 匹配字符串,请在前面的 [\000-\177]|
后面添加另一个 (
。
这个正则表达式确实很可怕,是的,但它也符合 POSIX,跨语言和跨平台兼容(不依赖于任何特殊的正则表达式符号,(应该)完全符合 UTF-8(Unicode 13),并且完全独立于区域设置。
如果你用这个运行 grep,请使用 grep -P
如果您只需要其他字节,那么其他人已经建议了。
如果您需要 11,172 个由 NFC 组成的韩文字符,它是
(([\352][\260-\277]|[\353\354][\200-\277]|
[\355][\200-\235])[\200-\277]|[\355][\236][\200-\243])
如果你需要日语平假名+片假名,那就是
([\343]([\201-\203][\200-\277]|[\207][\260-\277]))