如何使用Perl正则表达式捕获连字符单词中连字符的位置?
解决Perl中捕获连字符单词所有连字符位置的问题
你当前的代码里,正则表达式^(?:[\p{L&}0-9\.\'\/]{1,}([\-])){7,}[\p{L&}0-9\.\'\/]{1,}$无法捕获所有连字符位置,核心原因是重复的捕获组会覆盖之前的匹配结果——每次循环(?:...([\-]))时,捕获组1的内容都会被新匹配的连字符替换,最终只能拿到最后一个连字符的位置。
解决方案1:全局匹配逐个获取连字符位置
直接在单词中全局匹配连字符,每次匹配记录其在单词中的位置,再加上单词在文本中的起始偏移量得到绝对位置:
my $word = shift (@_); my $word_start_pos = shift (@_); my $text = shift (@_); # 全局遍历单词中的所有连字符 while ($word =~ /\-/g) { my $pos_in_word = $-[0]; # 当前连字符在单词内的起始位置 my $dash_pos_in_text = $word_start_pos + $pos_in_word; # 直接字符串比对比正则更高效 if (substr($text, $dash_pos_in_text, 1) eq '-') { load_changes('-', $dash_pos_in_text, 'Dash', ' ', 'Replace'); } }
解决方案2:先验证连字符数量再捕获位置
如果需要先确保单词包含至少7个连字符,再处理位置,可以先统计连字符数量,符合条件后再全局匹配:
my $word = shift (@_); my $word_start_pos = shift (@_); my $text = shift (@_); # 统计单词中的连字符总数 my $dash_total = () = $word =~ /\-/g; if ($dash_total >= 7) { # 遍历所有连字符位置 while ($word =~ /\-/g) { my $pos_in_word = $-[0]; my $dash_pos_in_text = $word_start_pos + $pos_in_word; if (substr($text, $dash_pos_in_text, 1) eq '-') { load_changes('-', $dash_pos_in_text, 'Dash', ' ', 'Replace'); } } }
关键说明
/-/g开启全局匹配后,每次调用=~会从上次匹配结束的位置继续查找,配合$-[0]可以获取当前匹配的连字符在$word中的起始索引。- 字符串直接比对
eq '-'比正则匹配/^[\-]$/更高效,适合单个字符的判断。
内容的提问来源于stack exchange,提问作者DavidS
相关产品推荐
相关产品推荐

