仅替换perl正则表达式中一行中第二次出现的字符串

时间:2015-08-07 12:31:54

标签: regex perl

我有一个像"ven|ven|vett|vejj|ven|ven"这样的字符串。处理每列的每个"|"分隔符。

"|"字符串拆分,保存数组中的所有列并将每列读入$str

所以,我试图这样做

$string =~ s/$str/venky/g if $str =~ /ven/i; # it will do globally. 

哪个不符合要求。

按需,我需要在特定的字符串出现次数替换字符串。

例如,我发出了将"ven"第二次更改为 venky 的请求。

那我怎么能简单地满足这个要求呢?是否有点像

$string =~ s/ven/venky/2; 

据我所知,我们有' o'替换一次,' g'为了全球。我努力寻求解决方案,以便在特定情况下获得替代品。我不应该使用pos()来获得这个位置,因为字符串会不断变化。每次都很难追踪它。这是我的意图。

请在这方面帮助我。

3 个答案:

答案 0 :(得分:1)

没有可以添加到执行此操作的正则表达式的标记。

最简单的方法是拆分和循环。但是,如果你坚持使用一个正则表达式,它是可行的:

/^(?:[^v]|v[^e]|ve[^n])*ven(?:[^v]|v[^e]|ve[^n])*\Kven/

如果您想要替换 N 次而非第二次出现,您可以这样做:

/^(?:(?:[^v]|v[^e]|ve[^n])*ven){N-1}(?:[^v]|v[^e]|ve[^n])*\Kven/

总体思路:

(?:[^v]|v[^e]|ve[^n])* - 匹配任何不属于ven

的字符串

\K是一个很酷的匹配器,可以删除到目前为止匹配的所有内容,因此您可以将其用作可变长度的后视镜

答案 1 :(得分:1)

目前,您正在更换&ven;' ven'与' venky'如果你的字符串包含ven的匹配项,那当然就是这样。

我认为你要做的就是用“替代”来代替' ven'为了' venky'在你的字符串中,如果它是第二个元素:

my $string = 'ven|ven|vett|vejj|ven|ven';

my @elements = split(/\|/, $string);

my $count;
foreach (@elements){
    $count++;
    s/$_/venky/g if /ven/i and $count == 2;
}

print join('|', @elements);
print "\n";

答案 2 :(得分:1)

你的方法已经相当不错了。你所描述的是有道理的,但我认为你在实施它时遇到了麻烦。

我创建了一个功能来完成这项工作。它需要4个参数:

  • $string是我们想要处理的字符串
  • $n是您要替换的 nth 出现
  • $needle是您想要替换的东西 - 针在大海捞针中

    请注意,现在我们允许传递可能包含正则表达式的内容。因此,您必须使用quotemeta或与/\Q$needle\E/

  • 匹配
  • $replacement$needle
  • 的替代品

想法是拆分字符串,然后检查每个元素是否与模式($needle)匹配,并跟踪已匹配的数量。如果到达第n个,请更换它并停止处理。然后将琴弦放回原处。

use strict;
use warnings;
use feature 'say';

say replace_nth_occurance("ven|ven|vett|vejj|ven|ven", 2, 'ven', 'venky');

sub replace_nth_occurance {
  my ($string, $n, $needle, $replacement) = @_;

  # take the string appart
  my @elements = split /\|/, $string;

  my $count = 0; # keep track of ...
  foreach my $e (@elements) {
    $count++ if $e =~ m/$needle/;    # ... how many matches we've found
    if ($count == $n) {
      $e =~ s/$needle/$replacement/; # replace
      last;                          # and stop processing
    }
  }

  # put it back into the pipe-separated format
  return join '|', @elements;
}

<强>输出

ven|venky|vett|vejj|ven|ven