Perl Regex для сжатия нескольких разрывов строк - PullRequest
3 голосов
/ 05 февраля 2011

Кажется, я не могу понять правильный синтаксис, но я хочу, чтобы регулярное выражение Perl находило два или более разрывов строки в строке и уплотняло их всего в 2 перевода строки.

Вот то, что я использую сегодня, но, похоже, не работает:

$string =~ s/\n\n+/\n\n/g;

Пожалуйста, дайте мне знать, что я делаю неправильно, и укажите правильное регулярное выражение Perl, которое я должен использовать.

Заранее спасибо за помощь!

Ответы [ 4 ]

7 голосов
/ 06 февраля 2011

Если вы используете 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 голосов
/ 05 февраля 2011

Это делает это:

#!/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;

0 голосов
/ 05 февраля 2011

@ btilly ударил гвоздь по голове. Я сделал быстрый тестовый пример:

in * * 1004

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 <>;
}
0 голосов
/ 05 февраля 2011

Показать полный пример.Что такое $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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...