正则表达式解析结果和预期不符,但看不出错在哪里了

>>> import re
>>> RE_FUNCTION_PARAM_NAME = '[\,\(;]\s*(.*?)\s*[\,:]'
>>> testStr = 'function Func(i: Integer; s1, s2,s3,s4: string): Boolean;'
>>> pattern = re.compile(RE_FUNCTION_PARAM_NAME)
>>> print pattern.findall(testStr)
['i', 's1', 's3']
>>> 

上面这段Python脚本,希望解析出testStr中的i、s1、s2、s3、s4

但是实际解析结果只有i、s1、s3

正确的正则表达式应该是什么样的?

阅读 2.8k
3 个回答

可以使用'[,(;]\s*(.*?)\s*(?=[,:])'

,(;:[]里面不是特殊字符,所以不用转义,当然转义了也没事;
你的正则的问题是正则最后会匹配一个逗号或者分号,所以下次匹配是从逗号或者分号的位置之后匹配的,所以当匹配成功s1之后,是从 s2,s3,s4: string): Boolean;'这个位置开始匹配的,因为开头的,号已经被s1匹配走了,所以下一次匹配是从s2后面的逗号开始的,所以s2匹配不上,同理s4前面的逗号让s3匹配走了,所以s4没有匹配上。

所以,我用断言匹配后面的逗号或分号。

Update1:
不用断言,可以使用这个

'[,(;]\s*([^,:\s)]+)'

因为变量名后面是空格或者逗号或者冒号或右括号,所以匹配的时候匹配[^,:\s]+,即一到多个非空格,逗号,冒号和右括号的字符就行了。

可以试下代码:

RE_FUNCTION_PARAM_NAME = '[,(;]\s*(.*?)\s*(?=[ \,:])'

原来的正则失败,原因在于后面的[\,:],因为正则在匹配的过程中,会有一个消费字符的过程,意思就是说,假设我匹配的这个字符,不管这个字符是不是我想要的,我都是消费了,在下次匹配就不会重复考虑,所以我用了零宽断言,这样就能光匹配但不消费,所以上一轮用于匹配的字符,在下一轮还能够继续使用

import re
RE_FUNCTION_PARAM_NAME = r'[(,\s]?([\d\w]+)[,:]'
testStr = 'function Func(i: Integer; s1, s2,s3,s4: string): Boolean;'
pattern = re.compile(RE_FUNCTION_PARAM_NAME)

print pattern.findall(testStr)

-> python test.py
['i', 's1', 's2', 's3', 's4']

直接用pattern用r''可以免去转义符号的烦恼了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏