在Perl中,如何匹配两个连续的回车符?

时间:2019-01-28 05:59:13

标签: regex windows perl match carriage-return

StackOverflow好友,

我在 Windows平台上;我有一个数据文件,但是出了点问题,并且(我不知道为什么)“回车+新行”的所有组合都变成了“回车+回车+新行”,(190128编辑:)例如:

以纯文本格式查看文件时,它是:

Text file in plain text (with unprintable stuffs)

以十六进制模式查看同一文件时,它是:

Text file in hex mode, can see the double "0D"s

出于实际目的,我需要删除双“ 0D”(如“ {.... 30 30 0D 0D 0A 30 30 ....”)中多余的“ 0D”,并将其更改为“ .... 30 30 0D 0A 30 30 ....”。

190129编辑:另外,为了确保可以重现我的问题,我将数据文件上传到了URL的GitHub(使用前应下载并解压缩;在二进制\十六进制编辑器中,您可以第一行中的0D 0D 0A):https://github.com/katyusza/hello_world/blob/master/ram_init.zip

我使用以下Perl脚本删除了多余的回车符,但令我惊讶的是我的正则表达式不起作用!我的整个代码是( 190129编辑:此处是整个Perl脚本的过去):

use warnings            ;
use strict              ;
use File::Basename      ;

#-----------------------------------------------------------
# command line handling, file open \ create
#-----------------------------------------------------------

# Capture input input filename from command line:
my $input_fn = $ARGV[0] or
die "Should provide input file name at command line!\n";

# Parse input file name, and generate output file name:
my ($iname, $ipath, $isuffix) = fileparse($input_fn, qr/\.[^.]*/);
my $output_fn = $iname."_pruneNonPrintable".$isuffix;

# Open input file:
open (my $FIN, "<", $input_fn) or die "Open file error $!\n";

# Create output file:
open (my $FO, ">", $output_fn) or die "Create file error $!\n";


#-----------------------------------------------------------
# Read input file, search & replace, write to output
#-----------------------------------------------------------

# Read all lines in one go:
$/ = undef;

# Read entire file into variable:
my $prune_txt = <$FIN> ;

# Do match & replace:
 $prune_txt =~ s/\x0D\x0D/\x0D/g;          # do NOT work.
# $prune_txt =~ s/\x0d\x0d/\x30/g;          # do NOT work.
# $prune_txt =~ s/\x30\x0d/\x0d/g;          # can work.
# $prune_txt =~ s/\x0d\x0d\x0a/\x0d\x0a/gs; # do NOT work.

# Print end time of processing:
print $FO $prune_txt  ;

# Close files:
close($FIN)     ;
close($FO)      ;

我竭尽所能匹配两个连续的回车,但是失败了。谁能指出我的错误,或告诉我正确的做法?预先感谢!

2 个答案:

答案 0 :(得分:2)

在Windows上,默认情况下,文件句柄具有:crlf层。

  • 此层在读取时将CR LF转换为LF。
  • 此层在写入时将LF转换为CR LF。

解决方案1:补偿:crlf层。

如果要以系统适合的行结尾作为结束,则可以使用此解决方案。

# ... read ...      # CR CR LF ⇒ CR LF
s/\r+\n/\n/g;       # CR LF    ⇒ LF
# ... write ...     # LF       ⇒ CR LF

解决方案2:删除:crlf层。

如果要无条件使用CR LF,则可以使用此解决方案。

使用<:raw>:raw代替<>作为模式。

# ... read ...      # CR CR LF ⇒ CR CR LF
s/\r*\n/\r\n/g;     # CR CR LF ⇒ CR LF
# ... write ...     # CR LF    ⇒ CR LF

答案 1 :(得分:1)

您的第一个正则表达式对我来说似乎工作正常,这意味着其他一些代码中可能存在问题。请提供Minimal, Complete, and Verifiable Example,这意味着包括样本输入数据等。

$ perl -wMstrict -e 'print "Foo\r\r\nBar\r\r\n"' >test.txt
$ hexdump -C test.txt 
00000000  46 6f 6f 0d 0d 0a 42 61  72 0d 0d 0a              |Foo...Bar...|
0000000c
$ cat test.pl 
#!/usr/bin/env perl
use warnings;
use strict;
use Data::Dump;

my $filename = 'test.txt';
open my $fh, '<:raw:encoding(ASCII)', $filename or die "$filename: $!";
my $prune_txt = do { local $/; <$fh> }; # slurp file
close $fh;

dd $prune_txt;
$prune_txt =~ s/\x0D\x0D/\x0D/g;
dd $prune_txt;

$ perl test.pl
"Foo\r\r\nBar\r\r\n"
"Foo\r\nBar\r\n"

顺便说一下,对我来说,文件使用的是哪种编码并不是立即显而易见的吗?在上面的示例中,您可能需要适当地调整:encoding(...)层。