我有几个非常大的XML文件,我正在尝试找到包含非ASCII字符的行。我尝试了以下方法:
grep -e "[\x{00FF}-\x{FFFF}]" file.xml
但是这会返回文件中的每一行,不管该行是否包含指定范围内的字符。
我是语法出错了还是做错了其他什么事情?我还尝试过:
egrep "[\x{00FF}-\x{FFFF}]" file.xml
(模式周围同时使用单引号和双引号)。
grep -v $'\u200d'
UTF-8
兼容序列\342\200\215
。这也不能同时是UTF-16
和UTF-32
,因为UTF-32
需要对所有代码点进行NUL
字节填充,但可以在little endian
中将UTF-16
字节序列定位于UTF-32
中作为前缀子字符串或在big endian
中作为后缀子字符串。 - RARE Kpop Manifestofile
用于自动化): 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,}
。
为了获得可读的Shell输出,uchardet $file
会猜测文件编码,并将其传递给iconv进行自动插值。
uchardet
命令。感谢您的提示! - bballdave025命令:
LC_ALL=C grep --color='auto' -obnP "[\x80-\xFF]" file.xml
输出:
868:31879:�
868:106287:�
868:106934:�
868:107349:�
868:254456:�
868:254678:�
868:286403:�
870:315585:�
870:389741:�
870:390388:�
870:390803:�
870:537910:�
870:538132:�
870:569811:�
870:598916:�
870:673324:�
870:673971:�
870:674386:�
870:821493:�
870:821715:�
870:853440:�
871:882578:�
871:956734:�
871:957381:�
871:957796:�
871:1104903:�
871:1105125:�
871:1136804:�
命令:
# Splitting the output of grep to ':'. Then printing the first 2 tokens and passing the 3rd one from xxd to convert to byte hex
LC_ALL=C grep --color='auto' -obnP "[\x80-\xFF]" file.xml |\
xargs -I{} bash -c "echo {}|awk 'BEGIN { FS = \":\" };{printf \"%s:%s:\",\$1, \$2; print \$3 | \"xxd -p -l1\" }'"
输出:
868:31879:96
868:106287:92
868:106934:92
868:107349:92
868:254456:92
868:254678:92
868:286403:92
870:315585:96
870:389741:92
870:390388:92
870:390803:92
870:537910:92
870:538132:92
870:569811:92
870:598916:96
870:673324:92
870:673971:92
870:674386:92
870:821493:92
870:821715:92
870:853440:92
871:882578:96
871:956734:92
871:957381:92
871:957796:92
871:1104903:92
871:1105125:92
871:1136804:92
更新 1:将主要的 awk
代码从 9
更改为 NF
,以处理前导和尾随的 ASCII
。
使用 awk
保持简单 - 利用 RS
实现无需区域调整的自动驾驶:
__=$'123=pqr:\303\606?\414#45&6\360\641\266\666]>^{(\13xyz'
printf '%s' "$__" | od
0000000 1026765361 980578672 205489859 641020963
1 2 3 = p q r : Æ ** ? \f # 4 5 &
061 062 063 075 160 161 162 072 303 206 077 014 043 064 065 046
1 2 3 = p q r : ? 86 ? ff # 4 5 &
49 50 51 61 112 113 114 58 195 134 63 12 35 52 53 38
31 32 33 3d 70 71 72 3a c3 86 3f 0c 23 34 35 26
0000020 3064066102 1581145526 2013997179 31353
6 ** ** ** ] > ^ { ( \v x y z
066 360 241 266 266 135 076 136 173 050 013 170 171 172
6 ? ? ? ? ] > ^ { ( vt x y z
54 240 161 182 182 93 62 94 123 40 11 120 121 122
36 f0 a1 b6 b6 5d 3e 5e 7b 28 0b 78 79 7a
0000036
printf '%s' "$__"
123=pqr:Æ?
#45&6]>^{(
xyz
mawk NF RS='[\0-\577]+' | gcat -b
1 Æ
2
为单行输出设置自定义ORS
:
gawk NF RS='[\0-\577]+' ORS='|' | gcat -b
Æ||
nawk NF RS='(\\0|[\1-\177]+)+'
由于 nawk
在处理字符类中的 \0
或 \\0
时存在问题,因此必须将其从 [...]
中取出,并用令人不安的冗长替代方案进行替换
如果你想要抓取/搜索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]))
LC_ALL=C rg -v '[[:ascii:]]' # --invert-match
brew install ripgrep
,也可以在Linux上安装。
也许我错过了什么,但我发现这是最简单和快速的替代方法。
nawk '/[\200-\377]/'
mawk '/[\200-\377]/'
gawk -b '/[\200-\377]/'
gawk -e '!/^[\0-\177]*$/'
gawk
的Unicode模式下,仅仅使用`/[^\0-\177]/`是不够的,因为它会忽略所有格式错误的序列和/或任意字节,比如\371
。
tr <file.txt -d '\000-\177' >foo.out && ls -al foo.out
来获取计数。然后可以使用od -x foo.out
查看实际值。 - Ron Burk