Perl(或其他) – ^ M的问题

我试图在Perl的每一个非空行的文本文件末尾添加"开始和结束",

 perl -pi -e 's/^(.+)$/\"$1\",/g' something.txt 

它增加了"在每个非空行的开始,但我有问题",

示例input:

 bla bla bla blah 

这是我得到的输出:

 "bla ", "bla bla ", "blah ", 

而这是我真正想要输出

 "bla", "bla bla", "blah", 

我该如何解决?

编辑:我现在在vim打开我的输出文件(我之前打开它在kwrite之前,所以它是不可见的),我注意到vim在每个之前显示^M ", – 我不知道在代码中增加了这一点。

看起来像一个行结束的问题 – 你在Windows中编辑文件? 尝试dos2unix

如果你不想使用dos2unix你可以匹配\ r:

 perl -pi -e 's/^(.+)\r$/\"$1\",/g' 

问题是,如果你在文件中有回报,它会匹配他们。*所以你会得到:

 "bla^M", "bla bla^M", "blah^M", 

您的数据文件必须源自Windows,它使用CRLF作为行分隔符而不是LF。 这意味着你的文本文件看起来像这样:

 bla[CR][LF]bla bla[CR][LF]blah[CR][LF] 

你可以使用od -c something.txt来验证。

 $ od -c something.txt 0000000 bla \r \nblabla \r \nbl 0000020 ah \r \n 0000024 

在Unix或Linux下,它会显示如下:

 bla\r bla bla\r blah\r 

当perl进行替换时,结果如下:

 "bla\r", "bla bla\r", "blah\r", 

当你捕捉到结果时,你会看到你所看到的:

 "bla ", "bla bla ", "blah ", 

简单的做法是使用dos2unix将行结束符转换为Unix格式,然后您的脚本将按预期运行。

在使用CRLF文本文件的系统上,Perl使用IO层来过滤CRLF,我们只在脚本中看到LF。 但是,如果在通常不使用CRLF的系统上打开CRLF文件,则可以通过多种方式启用CRLF转换。

你可以使用binmode 。 我在这里使用OO接口,因为我认为它更清洁,YMMV:

 use IO::File; open( my $fh, '<', 'winfile.txt' ) or die "Oh poo - $!\n"; $fh->binmode(':crlf'); 

你也可以使用调整开放:

 open( my $fh, '<:crlf', 'winfile.txt' ) or die "Oh poo - $!\n"; 

或者,您可以设置PERLIO环境变量(请参阅PerlIO ):

 PERLIO=crlf perl -pi -e 's/^(.+)$/\"$1\",/g' something.txt 

当然,这种方法将在处理文件中保留CRLF行结束符 – 这可能是也可能不是你想要的。

 sed 's/.\{1,\}/"&",/' 

这是在python或bash之前提出的- 在行尾添加“在行首”

既然你想在开始和结束时添加,你不需要用正则表达式替换这个简单的任务。

 perl -ne 'chomp;print "\"".$_."\",\n"' file