这是 gedit 编辑器的视图:
以及 vim 编辑器的视图:
然后我尝试 grep 它,如果我使用 Log 而不是 Tog,它会成功 grep,但输出已损坏:
[xiaobai@xiaobai grep]$ grep Tog test
[xiaobai@xiaobai grep]$ grep Log test
Dtring.valueOf
[xiaobai@xiaobai grep]$
然后我查看该文件,它也已损坏:
[xiaobai@xiaobai grep]$ cat test
Dtring.valueOf
[xiaobai@xiaobai grep]$
所以我使用十六进制转储:
[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]$
我缩小范围:
[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
正如你所看到的,在我附加一个 \x20 字节后,'a' 被删除了。
所以我的问题是,为什么会发生这种情况以及如何在事先不知道某些文件可能包含 \x0d\x20 (例如 grep -r )的情况下摆脱这种情况?
答案1
ASCII 码中的 0 到 31 的字符是控制字符。当发送到终端时,它们用于执行特殊操作。例如,\a
(BEL, 0x7) 会敲响终端的铃声。\b
(BS, 0x8) 向后移动光标。\n
(LF, 0xa) 将光标向下移动一行,\t
(TAB 0x9) 将光标移动到下一个表格...
\r
(CR, 0xd) 将光标移至第一列。
当您在终端中的 shell 提示符下运行时:
printf 'foo\nbar\n'
printf
写入,该设备的 tty 线路规则会将其转换为,这就是为什么您会foo\nbar\n
在后的下一行看到。/dev/tty<something>
foo\r\nbar\r\n
bar
foo
printf 'foo\rbar\n'
将使终端覆盖foo
为bar
.
如果您的文件包含控制字符,您可以删除它们,或者如果您想检查它们是否存在,则为它们提供文本表示(例如^M
CR 0xd 字符)。\r
不过,您可能不想对 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 $
请注意,那些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-_?'
仅将 ASCII 控制字符(TAB 和 LF 除外)转换为其^X
可视形式(但请注意,并非所有sed
实现都支持包含 NUL 字符的输入文件)。
答案2
\x0d
\r
是将光标带到行首的字符,然后\x20
是一个空格,因此它会a
用空格覆盖 。如果您使用的是 unix-y 系统,您可能需要考虑\r
从输出/文件中删除它,因为如果用于文本输出则不需要它。 “暗示”它\n
适用于 *nix,但不适用于 Windows。