Как сопоставить два экземпляра и заменить первый с помощью регулярного выражения в Perl? - PullRequest
3 голосов
/ 13 декабря 2011

Я хочу заменить только первый экземпляр, если возвращены два совпадения.

пример:

$sen = "The quick brown fox jump over the lazy dog, fox is quick";

как мне сопоставить только первый лиса и заменить егос волком и наоборот.

Вывод:

The quick brown wolf jump over the lazy dog, fox is quick 

или:

The quick brown fox jump over the lazy dog, wolf is quick 

Спасибо.

Ответы [ 4 ]

3 голосов
/ 13 декабря 2011

Подсчет совпадений с помощью глобальной опции /g, присвойте список совпадений пустому списку, чтобы получить счетчик (лучше, чем временная переменная).Первая замена является основной.Секунда использует счетчик, который увеличивается для каждого совпадения и заменяет в нужное время.

Обратите внимание на использование слова border \b для предотвращения ложных совпадений, таких как firefox, foxy lady и т. Д.

Код:

use strict;
use warnings;
use v5.10;   # only required for say, use print instead if your version is lower

my $fox  = 'fox';
my $wolf = 'wolf';
my $sen = "The quick brown fox jump over the lazy dog, fox is quick";

if ((()=$sen =~ /\b$fox\b/g) == 2) {   # counting matches 
    my $first = $sen;
    $first =~ s/\b$fox\b/$wolf/;       # replacing first
    my $second = $sen;
    my $i = 0;
    $second =~ s/\b$fox\b/ ++$i == 2 ? $wolf : $fox/eg;  # replacing second
    say for $first, $second;
}

Вывод:

The quick brown wolf jump over the lazy dog, fox is quick
The quick brown fox jump over the lazy dog, wolf is quick

Если вы хотите более многократно используемый код, вы можете сделатьподпрограмма из этого.

my $second = replace_nr($sen, $fox, $wolf, 2);
...
sub replace_nr {
    my ($str, $find, $replace, $num) = @_;
    my $i = 0;
    $str =~ s/\b($find)\b/ ++$i == $num ? $replace : $find/eg;
    return $str;
}

Вы можете даже использовать сабвуфер для обеих замен:

my $first  = replace_nr($sen, $fox, $wolf, 1);
my $second = replace_nr($sen, $fox, $wolf, 2);
2 голосов
/ 13 декабря 2011

Чтобы проверить, есть ли (как минимум) два, и заменить первое:

# The quick brown *wolf* jump over the lazy dog, fox is quick
s/fox(?=.*fox)/wolf/s;

Чтобы проверить, есть ли (как минимум) два, и заменить второе:

# The quick brown fox jump over the lazy dog, *wolf* is quick:
s/fox.*\Kfox/wolf/s;

s/(fox.*)fox/${1}wolf/s;  # Slower, but works pre 5.10
1 голос
/ 13 декабря 2011

По умолчанию оператор подстановки делает именно это: сопоставляет и заменяет первый случай.

Следующий оператор получит вашу первую строку вывода:

s/wolf/fox/
0 голосов
/ 13 декабря 2011

Ваш новый вопрос в том, что вы хотите считать

my $count = () = $text =~ /fox/g;

и заменить N-й экземпляр

my $n = 3;
my $nm1 = $n-1;
$text =~ s/(?:fox.*){$nm1}\Kfox/s;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...