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

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

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

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

[mercury@app01 ftp_logs]$ cat cl.txt
2015-01-22 03:00:01; local;

现在,当我查看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]$

用 替换空字节后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]

问题:

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

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

3) 相关文件是 Windows 计算机自动生成的文件。在什么情况下会^@进入文件。

答案1

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

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

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

cat不显示 ASCII-Nul btyes,有问题的终端仿真器会显示它们,但无论您使用什么终端仿真器都会忽略它们。如果您使用cat cl.txt | od -x或更好的cat cl.txt | xxd,您将在 的输出中看到 ASCII-Nul 字节cat。如果您在文件的前两个字节中看到类似“ffef”或“efff”的内容,则这些是 Microsoft 违反所有常识颁布的“字节顺序标记”。

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

答案2

  1. 是的,grep交换^@角色。 cat正在将字符打印到终端,但它们是您看不到的字符。仅仅因为您看不到这些角色并不意味着它们不存在。

  2. 您的选择/偏好,取决于哪一种最适合您的需求。但请记住,这vi有可能更改文件。

  3. ^@不是天生的性格。 Windows 程序正在主动将这些字符放在那里。要找出原因,你必须询问程序员。最有可能的是,Windows 程序假设字符为 16 位宽,而 Unix 机器则假设字符为 8 位宽。

答案3

我曾经也有过一样的问题。

vi了解文件字符集。

如果你使用

file c1.txt 

您可以查看它是 UTF-8 还是 ISO 文件。

之后,您可以使用转换实用程序将其转换

echo file iso-8859-1 is converted to UTF in order to be emailed
iconv -f 'iso-8859-1' -t UTF-8  $MESGFILE >>  $MESGENVIADO

相关内容