搜索不可打印的字符。 TLDR;执行摘要
- 搜索控制字符和扩展 unicode
- 区域设置,例如
LC_ALL=C 需要让 grep 完成您对扩展 unicode 的期望
所以首选的非 ascii 字符查找器:
$ perl -ne 'print "$. $_" if m/[\x00-\x08\x0E-\x1F\x80-\xFF]/' notes_unicode_emoji_test
在最佳答案中,逆 grep:
$ grep --color='auto' -P -n "[^\x00-\x7F]" notes_unicode_emoji_test
与最佳答案相同,但使用 LC_ALL=C:
$ LC_ALL=C grep --color='auto' -P -n "[\x80-\xFF]" notes_unicode_emoji_test
。 .更多的 。 .关于这个的令人难以忍受的细节:。 . .
我同意上面隐藏在 cmets 中的Harvey,搜索不可打印字符通常更有用,或者当您真的应该考虑不可打印时,很容易想到非 ASCII。 Harvey 建议“使用这个:“[^\n -~]”。为 DOS 文本文件添加 \r。转换为“[^\x0A\x020-\x07E]”并为 CR 添加 \x0D”
此外,在搜索不可打印字符时,将 -c(显示匹配的模式计数)添加到 grep 非常有用,因为匹配的字符串会弄乱终端。
我发现添加范围 0-8 和 0x0e-0x1f(到 0x80-0xff 范围)是一种有用的模式。这不包括 TAB、CR 和 LF 以及一两个不常见的可打印字符。所以恕我直言,一个非常有用(尽管很粗糙)的 grep 模式是这样的:
grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" *
实际上,通常您需要这样做:
LC_ALL=C grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" *
细分:
LC_ALL=C - set locale to C, otherwise many extended chars will not match (even though they look like they are encoded > 0x80)
\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 当前目录下所有文件的实例:
LC_ALL=C 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
更新:我最近不得不重新审视这个。而且,YYMV 取决于终端设置/太阳能天气预报但是。 .我注意到 grep 没有找到很多 unicode 或扩展字符。尽管直觉上它们应该匹配 0x80 到 0xff 的范围,但 3 和 4 字节的 unicode 字符不匹配。 ???谁能解释一下?是的。 @frabjous 询问,@calandoa 解释说 LC_ALL=C 应该用于设置命令的语言环境以使 grep 匹配。
例如我的语言环境LC_ALL= 为空
$ locale
LANG=en_IE.UTF-8
LC_CTYPE="en_IE.UTF-8"
.
.
LC_ALL=
LC_ALL= 为空的 grep 匹配 2 字节编码的字符,但不匹配 3 和 4 字节编码的字符:
$ grep -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" notes_unicode_emoji_test
5:© copyright c2a9
7:call underscore c2a0
9:CTRL
31:5 © copyright
32:7 call underscore
grep 与 LC_ALL=C 似乎确实匹配您想要的所有扩展字符:
$ LC_ALL=C grep --color='auto' -P -n "[\x80-\xFF]" notes_unicode_emoji_test
1:���� unicode dashes e28090
3:��� Heart With Arrow Emoji - Emojipedia == UTF8? f09f9298
5:� copyright c2a9
7:call� underscore c2a0
11:LIVE��E! ���������� ���� ���������� ���� �� �� ���� ���� YEOW, mix of japanese and chars from other e38182 e38184 . . e0a487
29:1 ���� unicode dashes
30:3 ��� Heart With Arrow Emoji - Emojipedia == UTF8 e28090
31:5 � copyright
32:7 call� underscore
33:11 LIVE��E! ���������� ���� ���������� ���� �� �� ���� ���� YEOW, mix of japanese and chars from other
34:52 LIVE��E! ���������� ���� ���������� ���� �� �� ���� ���� YEOW, mix of japanese and chars from other
81:LIVE��E! ���������� ���� ���������� ���� �� �� ���� ���� YEOW, mix of japanese and chars from other
这个 perl 匹配(部分在 stackoverflow 上的其他地方找到)或顶部答案上的逆 grep 似乎确实找到了所有 ~weird~ 和 ~wonderful~ “非 ascii”字符,而无需设置语言环境:
$ grep --color='auto' -P -n "[^\x00-\x7F]" notes_unicode_emoji_test
$ perl -ne 'print "$. $_" if m/[\x00-\x08\x0E-\x1F\x80-\xFF]/' notes_unicode_emoji_test
1 ‐‐ unicode dashes e28090
3 ? Heart With Arrow Emoji - Emojipedia == UTF8? f09f9298
5 © copyright c2a9
7 call underscore c2a0
9 CTRL-H CHARS URK URK URK
11 LIVE‐E! あいうえお かが アイウエオ カガ ᚊ ᚋ ซฌ आइ YEOW, mix of japanese and chars from other e38182 e38184 . . e0a487
29 1 ‐‐ unicode dashes
30 3 ? Heart With Arrow Emoji - Emojipedia == UTF8 e28090
31 5 © copyright
32 7 call underscore
33 11 LIVE‐E! あいうえお かが アイウエオ カガ ᚊ ᚋ ซฌ आइ YEOW, mix of japanese and chars from other
34 52 LIVE‐E! あいうえお かが アイウエオ カガ ᚊ ᚋ ซฌ आइ YEOW, mix of japanese and chars from other
73 LIVE‐E! あいうえお かが アイウエオ カガ ᚊ ᚋ ซฌ आइ YEOW, mix of japanese and chars from other
所以首选的非 ascii 字符查找器:
$ perl -ne 'print "$. $_" if m/[\x00-\x08\x0E-\x1F\x80-\xFF]/' notes_unicode_emoji_test
在最佳答案中,逆 grep:
$ grep --color='auto' -P -n "[^\x00-\x7F]" notes_unicode_emoji_test
与最佳答案相同,但使用 LC_ALL=C:
$ LC_ALL=C grep --color='auto' -P -n "[\x80-\xFF]" notes_unicode_emoji_test