Как я могу добавить вместо замены текста во время поиска и замены на Perl? - PullRequest
3 голосов
/ 01 июня 2009

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

Текст, который я ищу:

<space>Number<space>NumberNumberNumber

и я хочу заменить его на:

<space>Number<space>NumberNumberNumberI

У меня есть следующее регулярное выражение, которое работает при поиске строки:

\s[0-9]\s[0-9[0-9][0-9] 

Но что мне делать с заменой строки? По сути, я просто хочу добавить «Я» к концу.

Я использую:

perl -pi -e "s/\s[0-9]\s[0-9][0-9][0-9]/I/;" testFile 

но это заменяет все это на Я, а не добавляет к нему.

Ответы [ 2 ]

9 голосов
/ 01 июня 2009

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

s/(\s[0-9]\s[0-9]{3})/$1I/

С Perl 5.10 мы получили именованных захватов , так что вы можете сказать

s/(?<bodytext>\s[0-9]\s[0-9]{3})/$+{bodytext}I/

Имя между < и > - это имя. Имена становятся ключами в переменной %+, а значения являются захваченным текстом.

Другим решением является использование положительных просмотров нулевой ширины

s/(?<=\s[0-9]\s[0-9]{3})/I/

или его, новый для Perl 5.10, сокращение \K

s/\s[0-9]\s[0-9]{3}\K/I/

Попробуйте

perl -pi -e 's/(\s[0-9]\s[0-9][0-9][0-9])/$1I/' filename

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

perl -MO=Deparse -pi -e "s/(\s[0-9]\s[0-9][0-9][0-9])/$1I/" filename

Это даст следующий вывод.

BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/(\s[0-9]\s[0-9][0-9][0-9])/I/;
}
continue {
    print $_;
}
-e syntax OK

Отсюда видно, что $1 отсутствует. Попробуем еще раз с одинарными кавычками:

perl -MO=Deparse -pi -e 's/(\s[0-9]\s[0-9][0-9][0-9])/$1I/' filename
BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/(\s[0-9]\s[0-9][0-9][0-9])/$1I/;
}
continue {
    print $_;
}
-e syntax OK

И один раз с побегом:

perl -MO=Deparse -pi -e "s/(\s[0-9]\s[0-9][0-9][0-9])/\$1I/" filename
BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/(\s[0-9]\s[0-9][0-9][0-9])/$1I/;
}
continue {
    print $_;
}
-e syntax OK
0 голосов
/ 18 февраля 2018

Укороченная версия ответа от 2009 г. - вы можете использовать положительное утверждение нулевой ширины за утверждением , (?<=pattern) или \K, чтобы вставить что-то после вашего соответствия:

%echo "test" | perl -p -e "s/(?<=test)/ing/"
testing
%echo "test" | perl -p -e "s/test\K/ing/"
testing
%

В качестве альтернативы, чтобы вставить что-то перед совпадением, вы бы использовали положительное прогнозное утверждение нулевой ширины , (?=pattern):

%echo "test" | perl -p -e "s/(?=test)/#/"
#test
%

Справка:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...