StackOverflow好友,
我在 Windows平台上;我有一个数据文件,但是出了点问题,并且(我不知道为什么)“回车+新行”的所有组合都变成了“回车+回车+新行”,(190128编辑:)例如:
以纯文本格式查看文件时,它是:
以十六进制模式查看同一文件时,它是:
出于实际目的,我需要删除双“ 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) ;
我竭尽所能匹配两个连续的回车,但是失败了。谁能指出我的错误,或告诉我正确的做法?预先感谢!
答案 0 :(得分:2)
在Windows上,默认情况下,文件句柄具有:crlf
层。
解决方案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(...)
层。