Примечание от 2017 года: File :: Slurp не рекомендуется из-за ошибок проектирования и не поддерживаемых ошибок. Вместо этого используйте File :: Slurper или Path :: Tiny .
на ваш ответ
use File::Slurp ();
my $value = File::Slurp::slurp($filename);
$value =~ s/\R*//g;
File :: Slurp абстрагирует материал File IO и просто возвращает строку для вас.
Примечание
Важно отметить добавление /g
, без него, учитывая многострочную строку, он заменит только первый оскорбительный символ.
Кроме того, удаление $
, которое является избыточным для этой цели, так как мы хотим убрать все разрывы строк, а не только разрывы строк, прежде чем то, что подразумевается под $
на этой ОС.
В многострочной строке $
соответствует концу строки , и это будет проблематично).
Пункт 3 означает, что пункт 2 сделан с предположением, что вы также захотите использовать /m
в противном случае «$» будет в принципе бессмысленным для чего-либо практического в строке с> 1 строкой, или, делая однострочная обработка - операционная система, которая на самом деле понимает $
и находит \R*
, которая обрабатывает $
Примеры
while( my $line = <$foo> ){
$line =~ $regex;
}
Учитывая вышеприведенные обозначения, ОС, которая не понимает какие-либо разделители ваших файлов \ n или \ r в сценарии по умолчанию со стандартным разделителем ОС для $/
, приведет к чтению всего файла как одна смежная строка (если ваша строка не содержит разделителей $ OS, где она будет разделяться этим)
Так что в этом случае все эти регулярные выражения бесполезны:
/\R*$//
: удаляет только последнюю последовательность \R
в файле
/\R*//
: удаляет только первую последовательность \R
в файле
/\012?\015?//
: Когда будет стерта только первая последовательность 012\015
, \012
или \015
, \015\012
приведет к выдаче либо \012
, либо \015
.
/\R*$//
: Если в файле нет последовательности байтов '\ 015 $ OSDELIMITER', то NO разрывы строк будут удалены, за исключением собственных ОС.
Казалось бы, никто не понимает, о чем я говорю, поэтому вот пример кода, который проверен до НЕ удаление перевода строки. Запустите его, и вы увидите, что он оставляет перевод строки.
#!/usr/bin/perl
use strict;
use warnings;
my $fn = 'TestFile.txt';
my $LF = "\012";
my $CR = "\015";
my $UnixNL = $LF;
my $DOSNL = $CR . $LF;
my $MacNL = $CR;
sub generate {
my $filename = shift;
my $lineDelimiter = shift;
open my $fh, '>', $filename;
for ( 0 .. 10 )
{
print $fh "{0}";
print $fh join "", map { chr( int( rand(26) + 60 ) ) } 0 .. 20;
print $fh "{1}";
print $fh $lineDelimiter->();
print $fh "{2}";
}
close $fh;
}
sub parse {
my $filename = shift;
my $osDelimiter = shift;
my $message = shift;
print "Parsing $message File $filename : \n";
local $/ = $osDelimiter;
open my $fh, '<', $filename;
while ( my $line = <$fh> )
{
$line =~ s/\R*$//;
print ">|" . $line . "|<";
}
print "Done.\n\n";
}
my @all = ( $DOSNL,$MacNL,$UnixNL);
generate 'Windows.txt' , sub { $DOSNL };
generate 'Mac.txt' , sub { $MacNL };
generate 'Unix.txt', sub { $UnixNL };
generate 'Mixed.txt', sub {
return @all[ int(rand(2)) ];
};
for my $os ( ["$MacNL", "On Mac"], ["$DOSNL", "On Windows"], ["$UnixNL", "On Unix"]){
for ( qw( Windows Mac Unix Mixed ) ){
parse $_ . ".txt", @{ $os };
}
}
Для CLEARLY Необработанный вывод, см. Здесь: http://pastebin.com/f2c063d74
Обратите внимание, что есть определенные комбинации, которые, конечно, работают, но, скорее всего, это те, которые вы сами тестировали.
Обратите внимание, что в этом выводе все результаты должны иметь форму >|$string|<>|$string|<
с NO LINE FEEDS , чтобы считаться действительным выводом.
и $string
имеют общий вид {0}$data{1}$delimiter{2}
, где во всех выходных источниках должно быть либо:
- Ничего между
{1}
и {2}
- только
|<>|
между {1}
и {2}