4

我想通过在每行的开头添加行号来修改文件。我发现以下命令可以做到这一点:

cat file | perl -pe '$_ = "$. $_"' > file_with_line_numbers

这似乎有效,但是,当我在 vim 中打开文件时,它充满了 ^@ 和 ^M 字符。进一步调查表明编码已经改变。

> file -bi file
text/plain; charset=utf-16le

> file -bi file_with_line_numbers
application/octet-stream; charset=binary

我在这里想念什么?

4

2 回答 2

9

因为您没有对输入数据进行解码,也没有对输出数据进行编码,并且通过连接$.$_正在混合两种不同编码的数据(相反,您正在混合一个字节串和一个字符串,但是 perl 隐式地将字节字符串转换为字符串,并且以非常错误的方式来满足您的需要)。

一种解决方法是:

perl -pe  'BEGIN { binmode STDIN, ":encoding(utf16le)"; binmode STDOUT, ":encoding(utf16le)" } $_ = "$. $_";' < input > output
于 2013-01-02T17:22:41.360 回答
5

您需要解码程序的输入并对程序的输出进行编码。

正如 ysth 所指出的那样,这可以解决问题(Windows 除外,但可能使用 cygwin):

perl -Mopen=:std,':encoding(utf-16le)' -pe'$_="$. $_";' file.in >file.out

其余的原始答案:

如果你有 UTF-8,这是最容易做到的,因为你可以使用-CSDA.

<file.in iconv -f UTF-16le -t UTF-8 \
   | perl -CSDA -pe'$_="$. $_";' \
     | iconv -f UTF-8 -t UTF-16le \
       >file.out

由于 UTF-8 的特性,在这种情况下,您无需完全解码/编码就可以逃脱,允许您使用以下任一项:

<file.in iconv -f UTF-16le -t UTF-8 \
   | perl -pe'$_="$. $_";' \
     | iconv -f UTF-8 -t UTF-16le \
       >file.out

或者

<file.in iconv -f UTF-16le -t UTF-8 \
   | nl \
     | iconv -f UTF-8 -t UTF-16le \
       >file.out
于 2013-01-02T18:41:18.390 回答