В Perl, как сопоставить два последовательных возврата каретки? - PullRequest
0 голосов
/ 28 января 2019

Привет, друзья из StackOverflow,

Я на платформе Windows ;У меня есть файл данных, но что-то не так произошло, и (я не знаю почему) все комбинации «Возврат каретки + Новая строка» стали «Возврат каретки + Возврат каретки + Новая строка», (редактирование 190128:) Например:

При просмотре файла в виде обычного текста это:

Text file in plain text (with unprintable stuffs)

При просмотре того же файла в шестнадцатеричном режиме, это:

Text file in hex mode, can see the double

Из практических целей мне нужно удалить лишние "0D" в двойных "0D", таких как ".... 30 30 0D 0D 0A 30 30 ...."и измените его на ".... 30 30 0D 0A 30 30 ....".

190129 edit: Кроме того, чтобы убедиться, что моя проблема может быть воспроизведена, я загрузил свой файл данных в GitHub по адресу URL (следует загрузить &распакуйте его перед использованием; в двоичном редакторе \ hex вы можете 0D 0D 0A в первой строке): https://github.com/katyusza/hello_world/blob/master/ram_init.zip

Я использовал следующий скрипт на Perl, чтобы удалить дополнительный возврат каретки, но, к моему удивлению, мое регулярное выражениепросто НЕ работает !!Весь мой код ( 190129 edit : прошёл весь сценарий 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 голосов
/ 29 января 2019

В 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
0 голосов
/ 28 января 2019

Мне кажется, что первое из ваших регулярных выражений работает нормально, что означает, что может быть проблема в каком-то другом фрагменте кода.Пожалуйста, предоставьте Минимальное, Полное и проверяемое Пример , что означает включение выборочных входных данных и т. Д.

$ 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(...) соответствующим образом.

...