2013-11-06 4 views
0

Я пытаюсь заменить набор шаблонов с пробелами до и после их использования следующих регулярных выраженийматч Perl перекрывающихся последовательностей с условием

s/ $pattern/replacement /g 

Но это только преобразует первый из двух моделей в линии ($pattern $pattern => replacement $pattern)

Я попытался s/(? $pattern)/ replacement /g

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

Пример: Перед заменой, строка содержит ab ab. После

s/ ab/alphabeta/

Я получаю alphabeta ab

ответ

3
$_ = " foo foo foo "; 
s/ foo/bar /g; 
say; # " bar foo bar " 

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

Чтобы решить эту проблему, вы можете использовать обратные пути, чтобы не использовать пробелы. Например:

s/(?<=)foo(?=)/bar/g; 
say; # " bar bar bar " 

Или в вашем случае:

s/(?<=)$pattern(?=)/replacement/g 
+0

Спасибо, что цель '' (<=?)? – user13107

+0

@ user13107, '(? =)' Является lookahead, он соответствует только если следующее выражение соответствует внутреннему выражению (пробел в этом случае), но не продвигает позицию в строке и не включает ее в соответствие. '(? <=)' - это lookbehind, который работает одинаково, но вместо предыдущих символов. Для получения дополнительной информации см. ['Perlre'] (http://perldoc.perl.org/perlre.html#Look-Around-Assertions). – Qtax

4

В первой замене, пространство между паттернами является частью совпавшей строки, поэтому следующий соответствие начинается после пространства. Вы можете использовать нулевую ширину смотреть вперед утверждение, чтобы сделать положение не продвигалось по пространству:

my $s = ' a a a a a '; 
$s =~ s/ a(?=)/ X /g; 
print $s; 

Выход:

X X X X X 
Смежные вопросы