我有一个带有捕获组的正则表达式,可以在更广泛的上下文中匹配我想要的内容。然后,我使用捕获组$1
来满足我的需要。这很容易。
但是,如果我只想替换$1
中的内容而不是整个正则表达式,该如何使用s///
和捕获组呢?
例如,如果我执行以下操作:
$str =~ s/prefix (something) suffix/42/
prefix
和suffix
被移除。相反,我想用42
替换something
,同时保持prefix
和suffix
不变。
我有一个带有捕获组的正则表达式,可以在更广泛的上下文中匹配我想要的内容。然后,我使用捕获组$1
来满足我的需要。这很容易。
但是,如果我只想替换$1
中的内容而不是整个正则表达式,该如何使用s///
和捕获组呢?
例如,如果我执行以下操作:
$str =~ s/prefix (something) suffix/42/
prefix
和suffix
被移除。相反,我想用42
替换something
,同时保持prefix
和suffix
不变。
据我理解,您可以使用不消耗字符的向前或向后查找。或者将数据保存在组中,并仅删除您要查找的内容。例如:
使用前瞻:
s/your_text(?=ahead_text)//;
分组数据:
s/(your_text)(ahead_text)/$2/;
如果只需要替换一个捕获组,则可以使用@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"
使用环视断言。引用文档:
环视断言是零宽度模式,可以匹配特定的模式,而不包括在
$&
中。正向断言在其子模式匹配时匹配,负向断言在其子模式失败时匹配。回顾匹配到当前匹配位置之前的文本,前瞻匹配到当前匹配位置之后的文本。
如果字符串的开头具有固定长度,则可以这样做:
s/(?<=prefix)(your capture)(?=suffix)/$1/
?<=
对于变长模式不起作用(从Perl 5.30开始,它接受长度小于255个字符的变长模式,这使得可以使用|
,但仍然不能使用*
)。解决方法是使用\K
代替(?<=)
:
s/.*prefix\K(your capture)(?=suffix)/$1/
>something
开头的行为 >something_else
。适用于更改fasta序列的标题。 while ($filelines=~ />(.*)\s/g){
unless ($1 =~ /else/i){
$filelines =~ s/($1)/$1\_else/;
}
}
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表达式。