You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Perl循环输出正则捕获组时仅重复最后匹配结果?

Perl正则捕获组迭代时$1/$2重复输出的原因

先看你给出的三个命令:

前两个能正常输出所有捕获组内容:

echo 'jg984tj89g02jg09248gj4209jg49' | perl -0lne 'print "$_\n" for /(\d)([a-z])/gs'
echo 'jg984tj89g02jg09248gj4209jg49' | perl -0lne '@m = /(\d)([a-z])/gs; print for @m'

但第三个命令会重复输出最后一次匹配的捕获组:

echo 'jg984tj89g02jg09248gj4209jg49' | perl -0lne 'print "$1--> $2\n" for /(\d)([a-z])/gs'

问题原因

Perl里,当正则表达式在列表上下文(比如for循环的列表部分)执行时,/(\d)([a-z])/gs会返回一个扁平的列表——把所有匹配的捕获组依次排列,比如第一个匹配的$1、$2,第二个匹配的$1、$2……以此类推。

但for循环是在迭代这个列表里的单个元素,每次循环时$_会被设为列表里的某个值(比如先取第一个$1,再取对应的$2,接着下一个$1),但$1和$2这两个变量,只会保留最后一次完整正则匹配的结果,不会在循环迭代时更新。也就是说,整个正则表达式在进入循环前就已经执行完毕,所有捕获组都被提取到列表里了,$1/$2此时已经固定为最后一次匹配的值,循环里再调用它们自然只会重复输出同一个结果。

而前两个命令之所以正常:

  • 第一个直接打印迭代的$_,也就是列表里的每个捕获组值,自然能输出所有内容;
  • 第二个把列表存到数组@m后迭代打印,本质和第一个一样,都是直接取每个捕获组的结果。

解决方法

如果想逐个获取每个匹配的两组值并格式化输出,应该用while循环来逐个执行匹配,这样每次匹配都会更新$1和$2:

echo 'jg984tj89g02jg09248gj4209jg49' | perl -0lne 'while (/(\d)([a-z])/gs) { print "$1--> $2" }'

内容的提问来源于stack exchange,提问作者Signor Pizza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 23:04:55