Regex 删除多个用空格分隔的连续单词
在下面的代码中,模式Regex 删除多个用空格分隔的连续单词,regex,perl,Regex,Perl,在下面的代码中,模式/man/连续匹配两次。因此,当我替换该模式时,只有第一次出现的匹配,但第二次出现的不匹配 正如我所理解的问题,第一个模式本身匹配到第二个模式的开始(即,人之后的空间是第一个模式的结束,也是第一个模式的开始)。所以第二种模式不匹配。如何在连续出现时全局匹配此模式 use strict; use warnings; #my $name =" man sky man "; #this works my $name =" man man sky"; #this does
/man/
连续匹配两次。因此,当我替换该模式时,只有第一次出现的匹配,但第二次出现的不匹配
正如我所理解的问题,第一个模式本身匹配到第二个模式的开始(即,人之后的空间是第一个模式的结束,也是第一个模式的开始)。所以第二种模式不匹配。如何在连续出现时全局匹配此模式
use strict;
use warnings;
#my $name =" man sky man "; #this works
my $name =" man man sky"; #this does'nt
$name =~s/ man / nam /g; #expected= 'nam nam sky'
print $name,"\n";
正则表达式正在消耗它匹配的字符。所以,为了避免这种情况,在这种情况下应该使用lookahead和lookback来匹配它。检查 回头看:
(?我知道您想在空白字符或字符串的开始/结束之间替换man
在这种情况下,您可以使用两种方法,使用包含交替运算符的正查找框检查字符串边界和/或空白,或使用负查找框检查搜索词两端的非空白字符
使用以下两种方法之一:
$name =~ s/(?<=^|\s)man(?=\z|\s)/nam/g;
$name =~ s/(?<!\S)man(?!\S)/nam/g;
$name=~s/(?
从效率的角度来看,第二种选择更好,因为替代有点“昂贵”
(?(?!\S)
负先行断言在man
之后没有非空格
查看有关的更多详细信息。因此,“man-man-sky”
应该导致“man-nam sky”
,对吗?请精确回答这个问题。这看起来像是XY问题。如果要匹配整个单词,请使用\b
断言。因此,“man-man-man-sky”
应该导致“man-nam sky”
,对吗?请精确地回答这个问题。man-man-sky
应该变成nam-nam-sky
,然后你应该使用(参见)。更有效:s/man(?=)/nam/g
或s/\Kman(?=\s)/nam/g
(?=\n?\z)
,因此(?=$\124s)
意味着(?=\n?\z)
)
,这是一种复杂的编写(?=\s|\z)
请注意,您的替换几乎与s/\bman\b/nam/g
相同,这对于OP来说可能已经足够接近了。@ikegami如果目标是在空格或字符串的最后匹配,那么应该使用\z
(chomp
可以缓解这个问题。)(?!\S)和(?!\S)
环视词定义了空格边界而不是单词边界,因此尽管它们看起来相似,但它们却大不相同:\bman\b
匹配战争之人中的人,但是(?.Re“如果目标是”,则不会,(?=$)\S)
和(?=\s |\z)
就像我说的那样是等价的……但仍然不同
(?=pattern)
A zero-width positive lookahead assertion. For example, /\w+(?=\t)/ matches
a word followed by a tab, without including the tab in $&.
(?<=pattern) \K A zero-width positive lookbehind assertion. For
example, /(?<=\t)\w+/ matches a word that follows a tab, without
including the tab in $& . Works only for fixed-width lookbehind.
$name =~ s/(?<=^|\s)man(?=\z|\s)/nam/g;
$name =~ s/(?<!\S)man(?!\S)/nam/g;