Fru*_*uit 6 grep bash terminal cat
这是来自 gedit 编辑器的视图:
和 vim 编辑器的视图:
然后我尝试 grep 它,如果我把 Log 而不是 Tog,它确实 grep 成功,但输出已损坏:
[xiaobai@xiaobai grep]$ grep Tog test
[xiaobai@xiaobai grep]$ grep Log test
Dtring.valueOf
[xiaobai@xiaobai grep]$
Run Code Online (Sandbox Code Playgroud)
然后我找到文件,它也损坏了:
[xiaobai@xiaobai grep]$ cat test
Dtring.valueOf
[xiaobai@xiaobai grep]$
Run Code Online (Sandbox Code Playgroud)
所以我使用十六进制转储:
[xiaobai@xiaobai grep]$ hexdump -C test
00000000 4c 6f 67 2e 64 28 22 6d 75 73 69 63 22 2c 20 22 |Log.d("music", "|
00000010 4e 41 56 49 47 41 54 4f 52 3a 20 22 20 2b 20 53 |NAVIGATOR: " + S|
00000020 74 72 69 6e 67 2e 76 61 6c 75 65 4f 66 0d 20 20 |tring.valueOf. |
00000030 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | |
00000040 20 20 20 20 20 20 20 20 20 20 20 20 20 44 0d 0a | D..|
00000050
[xiaobai@xiaobai grep]$
Run Code Online (Sandbox Code Playgroud)
我缩小范围:
[xiaobai@xiaobai grep]$ cat test3
D
[xiaobai@xiaobai grep]$ hexdump -C test3
00000000 61 0d 20 20 20 20 20 20 20 20 20 20 20 20 20 20 |a. |
00000010 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | |
00000020 20 44 0d 0a | D..|
00000024
[xiaobai@xiaobai grep]$ echo -e '\x61'
a
[xiaobai@xiaobai grep]$ echo -e '\x61\x0d'
a
[xiaobai@xiaobai grep]$ echo -e '\x61\x0d\x20'
[xiaobai@xiaobai grep]$ echo -e '\x61\x0d\x20\x62'
b
Run Code Online (Sandbox Code Playgroud)
如您所见,“a”在我添加一个 \x20 字节后被删除。
所以我的问题是,为什么会发生这种情况,我如何在不知道某些文件可能包含 \x0d\x20 的情况下摆脱这种情况,例如 grep -r ?
Sté*_*las 14
ASCII 码 0 到 31 的字符是控制字符。当发送到终端时,它们被用来做特殊的事情。例如,\a
(BEL, 0x7) 使终端的铃响。\b
(BS, 0x8) 向后移动光标。\n
(LF, 0xa) 将光标向下移动一行,\t
(TAB 0x9) 将光标移动到下一个表格...
\r
(CR, 0xd) 将光标移动到第一列。
当您在终端中的 shell 提示符下运行时:
printf 'foo\nbar\n'
Run Code Online (Sandbox Code Playgroud)
printf
写入foo\nbar\n
到/dev/tty<something>
,该设备的TTY线路规程转换,要foo\r\nbar\r\n
,这就是为什么你看到bar
后的下一行foo
。
printf 'foo\rbar\n'
Run Code Online (Sandbox Code Playgroud)
会让终端foo
用bar
.
如果您的文件包含控制字符,如果您想检查它们的存在,您可以删除它们,或者给它们一个文本表示(例如^M
或\r
CR 0xd 字符)。
不过,您可能不想对 LF 和 TAB 字符执行此操作。所以:
LC_ALL=C tr -d '\0-\10\13-\37\177' < file # to remove them
cat -v < file # to display as ^M
sed -n l < file # to display as \r (also converts TAB to \t)
# and marks the end of lines with $
Run Code Online (Sandbox Code Playgroud)
请注意,那些sed
和cat
那些也将转换非 ASCII 字符。你可以这样做:
LC_ALL=C sed "$(printf 's/[^\t -\176\200-\377]/^&/g')" < file |
LC_ALL=C tr '\0-\10\13-\37\177' '@-HK-_?'
Run Code Online (Sandbox Code Playgroud)
仅将 ASCII 控制字符(TAB 和 LF 除外)转换为其^X
可视形式(请注意,并非所有sed
实现都支持其中包含 NUL 字符的输入文件)。