lzb1001 发表于 2022-4-29 09:52:14

请大神帮忙理解下正则表达式

>>> result = re.search(r'(\w+)(\w+)', 'I love FishC.com!') # search+无空格+.com
>>> result
<re.Match object; span=(2, 6), match='love'> # 为何无I?

>>> result = re.search(r'(\w+)(\w+)', 'I love FishC_com!') # search+无空格+_com
>>> result
<re.Match object; span=(2, 6), match='love'> # 为何无I?

>>> result = re.search(r'(\w+) (\w+)', 'I love FishC.com!') # search+1个空格+.com
>>> result
<re.Match object; span=(0, 6), match='I love'>

>>> result = re.search(r'(\w+) (\w+)', 'I love FishC_com!') # search+1个空格+_com
>>> result
<re.Match object; span=(0, 6), match='I love'>

>>> result = re.search(r' (\w+) (\w+)', 'I love FishC.com!') # search+2个空格+.com
>>> result
<re.Match object; span=(1, 12), match=' love FishC'> # 为何无I?

>>> result = re.search(r' (\w+) (\w+)', 'I love FishC_com!') # search+2个空格+_com
>>> result
<re.Match object; span=(1, 16), match=' love FishC_com'> # 为何无I?

>>> result = re.findall(r'(\w+)(\w+)', 'I love FishC.com!') # findall+无空格+.com
>>> result
[('lov', 'e'), ('Fish', 'C'), ('co', 'm')] # 看不懂结果

>>> result = re.findall(r'(\w+)(\w+)', 'I love FishC_com!') # findall+无空格+_com
>>> result
[('lov', 'e'), ('FishC_co', 'm')] # 看不懂结果

>>> result = re.findall(r'(\w+) (\w+)', 'I love FishC.com!') # findall+1个空格+.com
>>> result
[('I', 'love')] # 看不懂结果

>>> result = re.findall(r'(\w+) (\w+)', 'I love FishC_com!') # findall+1个空格+_com
>>> result
[('I', 'love')] # 看不懂结果

>>> result = re.findall(r' (\w+) (\w+)', 'I love FishC.com!') # findall+2个空格+.com
>>> result
[('love', 'FishC')] # 看不懂结果

>>> result = re.findall(r' (\w+) (\w+)', 'I love FishC_com!') # findall+2个空格+_com
>>> result
[('love', 'FishC_com')] # 看不懂结果

Twilight6 发表于 2022-4-29 10:19:55


最开始前两个为何无 I 的原因是 :

+ 是匹配前面的 1 至 多次,而你 I 只有一个字符,前后都没有在相邻的字母了

即只能匹配上 (\w+)(\w+) 前面一组正则,而后面一组匹配不上,自然就匹配失败。(\w+)(\w+) 的匹配最少需要两个字母

>>> result = re.search(r' (\w+) (\w+)', 'I love FishC.com!') # search+2个空格+.com
>>> result
<re.Match object; span=(1, 12), match=' love FishC'> # 为何无I?

' (\w+) (\w+)' 匹配不上 I 呀,I 前面没有空格,而你正则开始第一个就是空格


>>> result = re.findall(r'(\w+)(\w+)', 'I love FishC.com!') # findall+无空格+.com
>>> result
[('lov', 'e'), ('Fish', 'C'), ('co', 'm')] # 看不懂结果

因为你正则表达式中分组了,findall 返回的就是正则整组此时匹配到的结果

列表中一个 元组表示 匹配到的元素,元组中的正则元素对应每组匹配的元素

lzb1001 发表于 2022-4-29 10:47:57

Twilight6 发表于 2022-4-29 10:19
最开始前两个为何无 I 的原因是 :

+ 是匹配前面的 1 至 多次,而你 I 只有一个字符,前后都没有在相 ...

谢谢大神解疑释惑,以下第3个还是看不懂,不理解

1、ok

最开始前两个为何无 I 的原因是 :

+ 是匹配前面的 1 至 多次,而你 I 只有一个字符,前后都没有在相邻的字母了

即只能匹配上 (\w+)(\w+) 前面一组正则,而后面一组匹配不上,自然就匹配失败。(\w+)(\w+) 的匹配最少需要两个字母

2、ok

>>> result = re.search(r' (\w+) (\w+)', 'I love FishC.com!') # search+2个空格+.com
>>> result
<re.Match object; span=(1, 12), match=' love FishC'> # 为何无I?


' (\w+) (\w+)' 匹配不上 I 呀,I 前面没有空格,而你正则开始第一个就是空格

3、还是不理解:

---为何无I?
---为何表达式中无空格也能匹配得上?
---为何love拆分成lov+e,而不是其他比如lo+ve,FishC和com的拆分也不理解

>>> result = re.findall(r'(\w+)(\w+)', 'I love FishC.com!') # findall+无空格+.com
>>> result
[('lov', 'e'), ('Fish', 'C'), ('co', 'm')] # 看不懂结果


因为你正则表达式中分组了,findall 返回的就是正则整组此时匹配到的结果

列表中一个 元组表示 匹配到的元素,元组中的正则元素对应每组匹配的元素

Twilight6 发表于 2022-4-29 11:01:12

lzb1001 发表于 2022-4-29 10:47
谢谢大神解疑释惑,以下第3个还是看不懂,不理解

1、ok



---为何无I?

理由同问题1,(\w+)(\w+) 匹配最少需要两个字母相邻

---为何表达式中无空格也能匹配得上?

而空格在正则表达式中就是和普通符号一样,表示匹配字符中的 空格,正则匹配是去找里面符合表达式的字符,要理解正则匹配的原理

好好理解理解问题1的解释,\w 匹配字母,配合 + 号表示匹配 1~多个 字母,而匹配过程默认是贪婪匹配,会尽可能的匹配多个,

使用当 第一个 \w+ 开始匹配时,会尽量匹配到极限,而剩下最后一个字母给 第二个 \w+ 匹配,这样才保证可以匹配到,

这也是为什么 分组会呈现这种情况,你可以将第一个匹配带上 ? 号,表示非贪婪匹配,结果会正好和这字符串长度相反

'(\w+?)(\w+)'

lzb1001 发表于 2022-4-29 11:39:46

Twilight6 发表于 2022-4-29 11:01
理由同问题1,(\w+)(\w+) 匹配最少需要两个字母相邻




我测试了下面几个:

>>> result = re.search(r'(\w+?)(\w+)!', 'I love FishC_com!')
>>> result
<re.Match object; span=(7, 17), match='FishC_com!'>
>>> result = re.findall(r'(\w+?)(\w+)!', 'I love FishC_com!')
>>> result
[('F', 'ishC_com')]
>>> result = re.findall(r'(\w+)(\w+)!', 'I love FishC_com!')
>>> result
[('FishC_co', 'm')]

所以每行代码在回车运行之前,说实话真不知道返回的结果,不知道是不是因为还没有真正理解?

lzb1001 发表于 2022-4-29 11:49:49

Twilight6 发表于 2022-4-29 11:01
理由同问题1,(\w+)(\w+) 匹配最少需要两个字母相邻




如果我想匹配出如下完整的result结果,代码中……应如何写表达式呢?

>>> result = re.findall(r'……', 'I love FishC.com!')
>>> result
[('I'), ('love'), ('FishC'), ('com'), ('!')]

>>> result = re.findall(r'……', 'I love FishC_com!')
>>> result
[('I'), ('love'), ('FishC_com'), ('!')]

Twilight6 发表于 2022-4-29 12:11:56

lzb1001 发表于 2022-4-29 11:49
如果我想匹配出如下完整的result结果,代码中……应如何写表达式呢?

>>> result = re.findall(r'…… ...



'\w+|!'

lzb1001 发表于 2022-4-29 14:41:06

本帖最后由 lzb1001 于 2022-4-29 14:43 编辑

Twilight6 发表于 2022-4-29 12:11


'\w+|!'表示后面的字符串匹配w+或!,所以匹配的结果是:

w+匹配I love FishC com或I love FishC_com
!匹配!

是这个意思吗?

p.s:使用'\w+|!'将遗漏.com中的点.

Twilight6 发表于 2022-4-29 14:50:26

本帖最后由 Twilight6 于 2022-4-29 14:52 编辑

lzb1001 发表于 2022-4-29 14:41
'\w+|!'表示后面的字符串匹配w+或!,所以匹配的结果是:

w+匹配I love FishC com或I love FishC_com ...


findall 是查找多次,直到全部检索结束查找完毕,所以 \w+ 匹配 I love FishC.com! 字符串的过程是:

第一次贪婪匹配到 I ,结束,返回到列表中,然后从 I 后面空格开始继续匹配

第二次贪婪匹配成功是匹配到 love,匹配结束,返回到列表中,同理继续往下匹配

...

直到全部匹配结束,匹配出了 I、love、FishC.com ,不是一次性就直接匹配了 I love FishC.com 整个字符串,因为 \w 不与非字母以及下划线进行匹配

这样能理解吗?最后 \w+|! 就是每次匹配 \w+ 或 ! ,匹配成功就返回,同上类似步骤

lzb1001 发表于 2022-4-29 14:54:56

Twilight6 发表于 2022-4-29 12:11


如果要把'I love FishC.com!'里面的单词以及空格、点号.、感叹号!一个不拉的全部都匹配出来:

>>> result = re.findall(r'\w+|\s|\.|!', 'I love FishC.com!')
>>> result
['I', ' ', 'love', ' ', 'FishC', '.', 'com', '!']


有没有更简单的正则表达式可以实现上面的效果呢?

Twilight6 发表于 2022-4-29 14:58:29

lzb1001 发表于 2022-4-29 14:54
如果要把'I love FishC.com!'里面的单词以及空格、点号.、感叹号!一个不拉的全部都匹配出来:

>>> r ...



差不多就这样,我研究不深也不知如何简洁了

lzb1001 发表于 2022-4-29 15:12:52

Twilight6 发表于 2022-4-29 14:58
差不多就这样,我研究不深也不知如何简洁了

感谢大神的不吝赐教,谢谢!

>>> result = re.findall(r'\w+|\s|\.|!', 'I love FishC.com!')
>>> result
['I', ' ', 'love', ' ', 'FishC', '.', 'com', '!']

>>> result = re.findall(r'\w+|\s|!', 'I love FishC_com!')
>>> result
['I', ' ', 'love', ' ', 'FishC_com', '!']
页: [1]
查看完整版本: 请大神帮忙理解下正则表达式