正则表达式疑问

2016-11-14 17:38:33 +08:00
 explist
import re
a='abcabc'
b=re.search( r '(\d)abc(?(1)\d|abc)', a )
print(b)
#为何匹配失败? a='3abcabc'也是如此!
查了下(?(1)\d|abc) 的意思:如果编号为 1 的组匹配到字符,则需要匹配\d ,否则需要匹配 abc.
这里的 1 匹配到字符是指 c 后面匹配到字符呢还是 a 前面匹配到数字字符?
2405 次点击
所在节点    Python
21 条回复
slideclick
2016-11-14 17:54:43 +08:00
a='3abc3abc'成功
答案: 1 是 a 前面匹配到数字字符
icris
2016-11-14 17:59:59 +08:00
看后面的判断,你可能需要的表达式是 r'(\d)?abc(?(1)\d|abc)' ,你的表达式只有编号为 1 的组匹配到字符的情况,没有匹配不到的情况。
···
>>> re.search(r'(\d)?abc(?(1)\d|abc)', 'abcabc').group()
'abcabc'
···
explist
2016-11-14 18:31:20 +08:00
@slideclick
从概念上说, 1 确实是对第一个分组的匹配文本的引用。
这样问更准确:后面管道符 | 的左右两个子表达式选择时的判断依据是什么?是最前面的分组是否成功匹配(\d),还是 c 字符后面是否成功匹配( 1 )? 虽然最前面有数字字符(成功匹配了分组),但 c 后面仍然可能没有数字字符
explist
2016-11-14 18:35:41 +08:00
@icris
从这里看判断依据应该是 a 前面的分组是否匹配成功,而不是 C 后面的后向引用是否匹配
explist
2016-11-14 18:40:06 +08:00
@explist 这个理解有问题,困惑中
explist
2016-11-14 18:44:50 +08:00
'2abc1abc' : 这也能匹配成功?!!!
难道( 1 )是引用的'\d'本身,而不是对其匹配结果的引用? 这与 \1 明显不同
explist
2016-11-14 18:46:51 +08:00
这个问题来自此地址上图片的最末端
http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html#!comments
DiamondbacK
2016-11-14 19:14:44 +08:00
(1) 是判断 (\d) 是否匹配成功;
是,则接着尝试匹配 \d ,这跟捕获组 1 已经没有关系了,就是单纯的 \d ;
否,则尝试匹配 abc ,这就没有意义了,因为既然 (\d) 没有匹配到,那后面再怎么尝试,整个匹配式都是不匹配的,所以应该是 2 楼说的,正则表达式写错了,不是 (\d) 而是 (\d)?,它能匹配任何字符。
DiamondbacK
2016-11-14 19:21:35 +08:00
更正,原表达式中的 (\d) 一旦匹配失败,就没有后面的尝试了,因为一个正常的正则引擎已经可以判断在这个位置整个表达式匹配都失败了。
binux
2016-11-14 19:35:56 +08:00
@explist '2abc1abc' 能匹配成功是因为你用的是 search ,匹配的是 '2abc1'
chaleaoch
2016-11-14 21:42:14 +08:00
推荐这个: https://regex101.com/

另外还有一个可视化的工具。(但是刚才搜了一下没搜到。。。)
explist
2016-11-14 22:48:56 +08:00
If Clause (?(1)\d|abc)
Evaluate the condition below and proceed accordingly
(1) checks whether the 1st capturing group matched when it was last attempted
If condition is met, match the following regex \d
\d matches a digit (equal to [0-9])
Else match the following regex abc
abc matches the characters abc literally (case sensitive)
explist
2016-11-14 22:49:53 +08:00
@chaleaoch 谢谢
这句是什么意思:
If Clause (?(1)\d|abc)
explist
2016-11-14 22:50:45 +08:00
google 翻译:
如果条款(?( 1 )\ d | abc )
评估以下条件并相应地进行
( 1 )检查第一捕获组是否在最后一次尝试时匹配
如果条件满足,匹配以下正则表达式\ d
\ d 匹配数字(等于[0-9])
否则匹配以下正则表达式 abc
abc 匹配字符 abc 字面上(区分大小写)
explist
2016-11-14 22:55:39 +08:00
@explist
@icris 这样一改就好理解了,茅塞顿开
explist
2016-11-14 23:39:11 +08:00
这个有点奇怪,会回退去匹配
re.search(r'(\d)?abc(?(1)\d|abc)', '2abcabc')
结果为:‘ abcabc'
当经过(1)判断,进行第 2 个\d 匹配,失败后居然回到第一个 a 处重新开始又一次的正则式匹配,难道前面的匹配只有分组消耗字符???
mingyun
2016-11-14 23:42:23 +08:00
DiamondbacK
2016-11-14 23:53:03 +08:00
@explist
并没有退回,条件表达式 (?ifthen|else) 匹配失败所以自然没有消耗字符。
explist
2016-11-15 00:06:55 +08:00
@DiamondbacK 那也应该从第 2 个 a 开始,不是吗
DiamondbacK
2016-11-15 00:18:25 +08:00
@explist
因为条件表达式匹配失败,所以整个正则式在索引 0 匹配失败,所以挪到索引 1 进行匹配。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/320449

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX