在Perl中替换特定捕获组而不是整个正则表达式

时间:2012-08-26 14:59:51

标签: regex perl replace capture-group

我有一个正则表达式,其捕获组与我想要的更广泛的上下文相匹配。然后,我将捕获组$1用于满足我的需求。这很简单。

但是当我只想用替代品替换s///而不是整个正则表达式的内容时,如何将捕获组与$1一起使用?

谢谢!
-f

5 个答案:

答案 0 :(得分:15)

据我了解,您可以使用不消耗字符的前瞻或后视。或者将数据保存在组中,只删除您要查找的内容。例子:

预见:

s/your_text(?=ahead_text)//;

分组数据:

s/(your_text)(ahead_text)/$2/;

答案 1 :(得分:1)

如果您只需要替换一个捕获,那么使用@LAST_MATCH_START@LAST_MATCH_END(使用use English;与perldoc perlvar一起使用substr可能是可行的选择:

use English qw(-no_match_vars);
$your_string =~ m/aaa (bbb) ccc/;
substr $your_string, $LAST_MATCH_START[1], $LAST_MATCH_END[1] - $LAST_MATCH_START[1], "new content";
# replaces "bbb" with "new content"

答案 2 :(得分:1)

这是一个老问题,但我发现以下更容易将以>something开头的行替换为>something_else。适合更改fasta序列的标题

  while ($filelines=~ />(.*)\s/g){
        unless ($1 =~ /else/i){
                $filelines =~ s/($1)/$1\_else/;
        }

  }

答案 3 :(得分:0)

我使用这样的东西:

s/(?<=prefix)(group)(?=suffix)/$1 =~ s|text|rep|gr/e;

示例:

在下面的文本中,我想标准化::=之后的空白,但

some    text     := a   b        c d   e   ;

可以通过以下方式实现:

s/(?<=::=)(.*)/$1 =~ s|\s+| |gr/e

结果:

some    text     := a b c d e ;

说明:

(?<=::=):后视断言以匹配 ::=

(.*)::=

之后的所有内容

$1 =~ s|\s+| |gr:使用捕获的组规范化空格。请注意 r 修饰符,它确保不要尝试修改只读的 $1。使用不同的子分隔符 (|) 不终止替换表达式。

/e:将替换文本视为 perl 表达式。

答案 4 :(得分:0)

使用lookaround assertions。引用文档:

<块引用>

环视断言是零宽度模式,它匹配特定模式而不将其包含在 $& 中。当子模式匹配时肯定断言匹配,当子模式失败时否定断言匹配。 Lookbehind 匹配到当前匹配位置的文本,lookahead 匹配当前匹配位置之后的文本。

如果字符串的开头有固定长度,你可以这样做:

s/(?<=prefix)(your capture)(?=suffix)/$1/

然而,?<= 不适用于变长模式(从 Perl 5.30 开始,它接受长度小于 255 个字符的变长模式,这允许使用 |,但仍然阻止* 的使用)。解决方法是使用 \K 而不是 (?<=)

s/.*prefix\K(your capture)(?=suffix)/$1/