Перекрывающаяся подстановка текста регулярным выражением Perl - PullRequest
4 голосов
/ 17 января 2012

У меня есть текстовый файл, который содержит несколько предложений.Предложения содержат пробелы (пробелы, символы табуляции, новые строки) для выделения слов, состоящих из букв и / или цифр.Я хочу найти слово «123» или «-123» и вставить точку (.) До начала цифр.Таким образом, все вхождения «123» и «-123» будут преобразованы в «.123» и «-.123».

Я пробовал это со следующим:

$line =~ s/(\s+-*123\s+)/getNewWord($1)/ge

Где $ line содержит строку, прочитанную из файла, а функция getNewWord word поместит точку (.) В соответствующее место в совпавшем слове.

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

Может ли кто-нибудь помочь мне с этим?Спасибо!

Ответы [ 5 ]

5 голосов
/ 18 января 2012

Я согласен с MRAB (и получил +1 ответ), но для функции getNewWord нет особой необходимости.Я бы изменил все утверждение на что-то вроде этого:

$line =~ s/((?:^|\s)-?)(123)(?=\s|$)/$1.$2/g;

$line =~ s/(?:^|(?<=\s))(-?)(123)(?=\s|$)/$1.$2/g;

$line =~ s/(?:^|(?<=\s)|(?<=\s-))(?=123(?:\s|$))/./g;
4 голосов
/ 18 января 2012

Это может быть немного быстрее (без явного захвата), и это позволяет файл без пробела в начале / конце:

$ echo '123 -123 -123  123' | perl -pe's/(?:^|\s+)\K(?=-?123\b)/./g'
.123 .-123 .-123  .123

ставить . после -:

$ echo '123 -123 -123  123' | perl -pe's/(?:^|\s+)-*\K(?=123\b)/./g'
.123 -.123 -.123  .123
2 голосов
/ 18 января 2012

Попробуйте использовать позитивный взгляд так: (\s+-*123)(?=\s).

1 голос
/ 18 января 2012

Это напомнило мне об этом вопросе: Поиск html-файла для случайной строки с использованием регулярного выражения , где я нашел (было показано) хорошее применение для отрицательных проверочных утверждений, то есть сопоставления необязательных разделителей и избежание частичных совпадений.

Совпадение -?123 простое, проблемы:

  1. Несоответствие частичных строк
  2. Предотвращение несовпадений начала / конца строки
  3. Избегайте перемещения якоря \G
  4. . Слежу за утверждением необязательного тире -?

Мне не удалось решить # 4, так как утверждения с изменяемой длиной смотрят за спиной.не поддерживается, поэтому исправление использует группу захвата.

Обратите внимание, что некоторые другие ответы на этот вопрос не решают эти проблемы.

Объяснение:

Отрицательное утверждение за непропущенным пробеломсоответствует как пробел, так и начало строки, и гарантирует, что мы не сопоставляем частичные строки.Затем следует дополнительная черта в группе захвата.Конец совпадения - это вложенный запрос, где мы должны сопоставить 123, за которым следует все, что не является пробелом.

Код:

use strict;
use warnings;

while(<DATA>) {
    s/(?<!\S)(-?)(?=123(?!\S))/$1./g;
    print;
}

__DATA__
r 123 z123 "123" -1233 d123 123-123
123 -123 -123 123 123

Выход:

r .123 z123 "123" -1233 d123 123-123
.123 -.123 -.123 .123 .123
0 голосов
/ 18 января 2012

Или просто это?Это не беспокоит насчет пробелов и работает на Perl 5.8.

echo '123 -123 -123  123' | perl -pe's/(-)?(123)/$1.$2/g'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...