Python 2.7.6 (default, Nov 23 2017, 15:49:48)
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> re.search("(switchport)?", " switchport trunk allowed vlan 10").groups()
(None,)
>>> re.search("(switchport)", " switchport trunk allowed vlan 10").groups()
('switchport',)
如上,为什么加了问号后,匹配出来的就变成 None 了?难道问号不能作用于一个 group ?
如果我要用从 m.groups() 中判断是否匹配了特定关键字,需要怎么写?
1
Enochyun 2018-01-25 15:22:59 +08:00
你匹配的内容里面没有?号 当然是 none 了。
|
3
wlsnx 2018-01-25 15:24:41 +08:00 1
In [23]: re.search?
Signature: re.search(pattern, string, flags=0) Docstring: Scan through string looking for a match to the pattern, returning a match object, or None if no match was found. File: ~/.pyenv/versions/3.6.4/lib/python3.6/re.py Type: function 找到一个匹配就返回,很明显 "(switchport)?" 可以匹配 "" |
4
feng32 OP @wlsnx 那么如果我要实现匹配 n 个可选关键字,应该就不能把正则写成 (aaa)?( bbb)?( ccc)? 的形式了,这种情况有解决方法吗?
|
5
imn1 2018-01-25 15:33:51 +08:00
没看过源码,但从经验来看,py 的 re 基本上是最小匹配优先
例如 findall 如果出现两个“零或多个”不定长度,匹配结果就往往不是预期结果了 |
6
geelaw 2018-01-25 15:34:40 +08:00
你可以写 aaa|bbb|ccc,如果你一次只想要一个。
或者采用展开的形式:aaa(bbb)?(ccc)?|bbb(ccc)?|ccc |
7
wlsnx 2018-01-25 15:36:21 +08:00
你在这些可选关键字周围加一些必选关键字就行了
|
8
scriptB0y 2018-01-25 15:39:15 +08:00
这是一个正则表达式的问题,和 Python 没什么关系。
你应该看一下贪心 match 和惰性 match 的却别 https://stackoverflow.com/questions/2301285/what-do-lazy-and-greedy-mean-in-the-context-of-regular-expressions > 那么如果我要实现匹配 n 个可选关键字 这个在 python 里面不用匹配,用搜索比较好一些。re.findall(r"(aaa|bbb|cc)", string) |
9
Aevery 2018-01-25 15:40:40 +08:00
*相当于匹配最少 0 到无限次, +相当于匹配最少 1 次到无限次,而 ?是匹配最少 0 次到最多 1 次。。。lz 可以试试用”+“
|
10
feng32 OP @scriptB0y 实际上更完整的场景是这样的
我设计了一个简单的模板语言,支持 blablabla {var1} {var2} bla <flag1> <flag2> blabla 这样的语法 {var1} 是一个变量,编译成了正则表达式 ([^ ]+) <flag1> 是一个可选参数,可以出现 0 次 或 1 次,编译成了正则表达式 (flag1)? 最后将所有捕捉到的 regex groups 再映射到原变量返回给用户 这个模板本身是灵活的,用户可以把 <flag1> 放在最前面,甚至也可以一行就一个 <flag1> 这种情况下感觉启用贪婪匹配模式就可以解决问题了吧? |
11
p2pCoder 2018-01-25 15:48:58 +08:00
```
import re re.search("(switchport)?", " switchport trunk allowed vlan 10").groups() (None,) re.findall("(switchport)?", " switchport trunk allowed vlan 10") ['', '', 'switchport', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''] re.search("(switchport)+", " switchport trunk allowed vlan 10").groups() ('switchport',) re.findall("(switchport)+", " switchport trunk allowed vlan 10") ['switchport'] ``` |
15
scriptB0y 2018-01-25 16:09:14 +08:00
@feng32 你这是一个词法分析了吧,可以看一下内置的库 https://docs.python.org/3.6/library/shlex.html
|
16
feng32 OP @scriptB0y 实际上就是一个以正则表达式为中间代码的模板解析器,当我用 30 行 Python 把它写出来的时候自己也挺惊讶的,而且发现它也挺好用的,今天刚遇到这个问题
正规的词法分析、语法分析之前上大学的时候也做过,不过暂时不准备替换重量级的方案; shlex 这个库听过但是没详细了解,后面可以花点时间看看 |
17
windvans 2018-01-25 21:11:24 +08:00
?可以匹配 0 次,这个可能是和 python 的 re 匹配原则有关,如果是贪心的话,应该先匹配有的
你这个确实用 find 比较好 |
18
zhangsen1992 2018-01-26 11:55:23 +08:00
?
|