Perl Regex To Condense Несколько разрывов строк
Я не могу понять правильный синтаксис, но я хочу, чтобы регулярное выражение Perl находило, где есть две или более разрывов строк в строке, и конденсирует их только в 2 разрыва строки.
Вот что я использую сегодня, который, похоже, не работает:
$string =~ s/\n\n+/\n\n/g;
Пожалуйста, дайте мне знать, что я делаю неправильно, и правильное регулярное выражение Perl, которое я должен использовать.
Заранее благодарим за помощь!
Ответы
Ответ 1
Если вы используете Perl 5.10 или новее, попробуйте следующее:
$string =~ s/(\R)(?:\h*\R)+/$1$1/g;
\R
- это общая escape-последовательность разделителя строк (ref), а \h
соответствует любому горизонтальному символу пробела (например, пространство и TAB) (ref). Таким образом, это преобразует любую последовательность одной или нескольких пустых строк в одну пустую строку.
Большинство приложений в наши дни либеральны в том, что они распознают как разделитель строк; они даже согласятся на сочетание двух или более стилей разделителя в том же документе. С другой стороны, некоторые приложения активно конвертируют все разделители строк в один предпочтительный стиль. Но иногда вам приходится придерживаться определенного стиля; поэтому я взял первое совпадение \R
и использовал его в качестве замены вместо произвольного использования \n
.
Имейте в виду, что эти специальные escape-последовательности не широко поддерживаются в других вариантах регулярных выражений. Они работают в последних версиях PHP, а \R
, похоже, работает в Ruby 2.0, хотя я не могу найти какой-либо документ, который упоминает об этом. Ruby 1.9.2 и 2.0 поддерживают escape-последовательность \h
, но она соответствует шестнадцатеричной цифре ([0-9a-fA-F]
), а не горизонтальному пробелу. В большинстве других ароматов \R
и \h
будут либо выдавать исключение, либо соответствовать буквальным R
и h
соответственно.
Ответ 2
Это делает:
#!/usr/bin/env perl
use strict;
use warnings;
my $string;
{
local $/=undef;
$string =<DATA>;
}
print "Before:\n$string\n============";
$string=~s/\n{2,}/\n\n/g;
print "After:\n$string\n\nBye Bye!";
__DATA__
Line 1
Line 2
Line 9
Line 10
Line 12
Line 16
Line 19
Вывод:
Before:
Line 1
Line 2
Line 9
Line 10
Line 12
Line 16
Line 19
============After:
Line 1
Line 2
Line 9
Line 10
Line 12
Line 16
Line 19
Perl также поддерживает класс символов \R
для независимости платформы. См. эту ссылку SO. Тогда ваше регулярное выражение будет s/\R{2,}/\n\n/g;
Ответ 3
Покажите полный пример. Что такое $string
?
$ perl -E'my $s = qq{a\n\n\nb}; say "[$s]"; $s =~ s/\n\n+/\n\n/g; say "[$s]"'
[a
b]
[a
b]
Ответ 4
@btilly ударил ноготь по голове. Я сделал быстрый тестовый пример:
in
:
a
b
c
с помощью этого кода:
my $line = join '', <>;
$line =~ s{\n\n+}{\n\n}g;
print $line;
и он вернул ожидаемый результат:
a
b
c
Вы можете получить тот же результат, изменив разделитель записей (и избегая регулярного выражения):
{
# change the Record Separator from "\n" to ""
# treats multiple newlines as just one (perldoc perlvar)
# local limits the change to the global $/ to this block
local $/ = "";
print <>;
}