字符在 vi 中可见,但在 cat 中不可见。

Cit*_*ght 4 grep character-encoding cat

我有一个 300 行的文件,文件中的^@每个字符之间都有字符。

(出于安全原因,我无法发布全部内容,所以我只粘贴了第一行)

[mercury@app01 ftp_logs]$ cat cl.txt
2015-01-22 03:00:01; local;
Run Code Online (Sandbox Code Playgroud)

现在,当我vi打开文件时,我看到以下相同的内容:

2^@0^@1^@5^@-^@0^@1^@-^@2^@2^@ ^@0^@3^@:^@0^@0^@:^@0^@1^@;^@ ^@l^@o^@c^@a^@l^@;^@

由于cat不显示^@字符,自然我认为对某个字符串进行 grep 可以在cat.

[mercury@app01 ftp_logs]$ cat cl.txt
2015-01-22 03:00:01; local;
[mercury@app01 ftp_logs]$ cat cl.txt | grep local
[mercury@app01 ftp_logs]$
Run Code Online (Sandbox Code Playgroud)

用 替换空字节后sed,文件现在可以读取vigrep从 返回结果cat

[mercury@app01 ftp_logs]$ sed -i 's/\x0//g' cl.txt
[mercury@app01 ftp_logs]$ cat cl.txt | grep local
2015-01-22 03:00:01; local;
[mercury@app01 ftp_logs]
Run Code Online (Sandbox Code Playgroud)

问题:

1) 为什么grep在替换空字节之前不起作用,因为没有显示空字节。这是否意味着即使没有显示在终端中也grep看到了^@字符?

2)这让我想知道是否建议使用cat -vvi读取生产服务器上的文件,因为cat似乎隐藏东西很好?

3) 有问题的文件是从 Windows 机器自动生成的文件。在什么情况下会^@进入文件。

Bru*_*ger 5

该文件的格式可能是小端 UTF-16。Windows 上的一些应用程序似乎默认为这个,并且它会导致很多可移植性问题。

vi将 ASCII-Nul(数字为零)值字节表示为“^@”(控制-At)。您实际上可以vim使用 control-shift-@ 和弦输入零值字节。

grep必须查看 ACII-Nul 字节,而不是将文件解释为 UTF-16,然后查看“2”或“0”等的 Unicode 代码点。我在 GNUgrep手册页中没有看到用于处理 UTF-anything 的选项。

cat不显示 ASCII-Nul 字节,有问题的终端仿真器会显示它们,但无论您使用什么终端仿真器,都会忽略它们。如果您使用cat cl.txt | od -x或更好的 ,cat cl.txt | xxd您将在cat. 如果你看到像 'ffef' 或 'efff' 这样的东西作为文件的前两个字节,那是微软违反所有常识颁布的“字节顺序标记”。

我不确定推荐什么来将 UTF-16 音译为 ASCII 或 UTF-8,iconv也许,但我从未使用过它。