Со всем файлом в скаляре напишите свой шаблон, чтобы он захватывал строки до и после line3
. Модификатор /m
особенно полезен:
Рассматривать строку как несколько строк. То есть измените ^
и $
с соответствия начала или конца строки на совпадение с началом или концом любой строки в любом месте строки.
Шаблоны ниже используют модификатор /x
, который позволяет нам добавлять пробелы, чтобы они выглядели так, как они соответствуют.
Например:
#! /usr/bin/perl
my $data = do { local $/; <DATA> };
my $pattern = qr/ ^(.+\n)
^line3\n
^(.+\n)
/mx;
if ($data =~ /$pattern/) {
print $1, $2;
}
else {
print "no match\n";
}
__DATA__
line1
line2
line3
line4
line5
Выход:
line2
line4
Помните, что $
- это утверждение: оно не потребляет никаких символов, поэтому вы должны сопоставлять символ новой строки с буквенным шаблоном \n
.
Также обратите внимание, что приведенному выше шаблону не хватает общности. Он отлично работает для линии где-то посередине, но не удастся, если вы измените line3
на line1
или line5
.
Для случая line1
можно сделать предыдущую строку необязательной с помощью квантификатора ?
:
my $pattern = qr/ ^(.+\n)?
^line1\n
^(.+\n)
/mx;
Как и ожидалось, получается
line2
Но пытаясь исправить то же самое для line5
дела
my $pattern = qr/ ^(.+\n)?
^line5\n
^(.+\n)?
/mx;
дает
no match
Это потому, что после последнего перехода на новую строку в файле (после line5
), ^
некуда найти, но шаблон меняется на
my $pattern = qr/ ^(.+\n)?
^line5\n
(^.+\n)?
/mx;
выходы
line4
Мы могли бы остановиться здесь, но асимметрия в шаблоне неприятна. Почему работал для одного случая, а не для другого? С line1
, ^
соответствует началу $data
, а затем ничего не соответствует (.+\n)?
.
Помните: шаблоны, количественно определяемые с ?
или *
всегда , успешны, потому что они семантически совпадают с
- ноль раз или один раз
- ноль или более раз
соответственно и что угодно может совпадать с нулем раз:
$ perl -le 'print scalar "abc" =~ /(?!)*/'
1
Хотя я не могу вспомнить время, когда я когда-либо видел, чтобы оно использовалось таким образом, квантификатор {m,n}
, где m равен нулю, например, ,
всегда будет успешным, потому что m - это минимальное количество повторений. Квантор {0}
является патологическим случаем, включенным для полноты.
Все, что нужно было показать, нам более или менее повезло с делом line1
. ^
соответствует самому началу, ?
-квантованный образец ничего не соответствует, а затем следующий ^
также соответствует самому началу $data
.
Восстановление симметрии делает рисунок чище:
my $pattern = qr/ (^.+\n)?
^line5\n
(^.+\n)?
/mx;