- == 系统问题,暂停聊天功能。==
- 【征集】西西河的经济学,及清流措施,需要主动参与者,『稷下学宫』新认证方式,24年网站打算和努力目标
主题:文问题,关于正则表达式 -- pastebt
正则语言比普通语言好像是差了什么功能,记得有1个分类,不过我很久不搞这些都忘了,编译原理学的比较好的应该清楚。
面壁去了
一句SQL是能办到,但就不是正则了。
等各位的高招
perl正则表达式里头有种特殊的括号:
(?=...)
True if lookahead assertion succeeds.
(?!...)
True if lookahead assertion fails.
(?<=...)
True if lookbehind assertion succeeds.
(?<!...)
True if lookbehind assertion fails.
可以满足你的要求. 查一下programming perl的table 5.6吧.
写这种正则表达式挺费脑子的, 我就不写例子了
(?<=a\w*)3(?=\w*b)
个人看法,正则表达式上手倒不会很难,然而其表达式可读性却非常差。因此实际使用中的困难在于如何维护这种可读性极差的正则代码。(它的确是一种代码,一种字符串匹配程序的代码)
我的方法是采用结构化方式,一层层剥下来。比如楼主的问题可以分成三块:
1、a开始的边界条件
2、匹配字符3
3、以b结束的边界条件
这样可以一个复杂的匹配就被分解成若干个简单的匹配,写起来也就简单很多了。和写程序一样,如果第一次分解还得不出可以立即翻译的正则表达式,我们还可以进一步分解。
而在实际代码中我就会使用字符串模板替换来还原上述过程。其伪代码很像这样:
REG := LEFT_BORDER + MATCH_CHAR + RIGHT_BORDER
LEFT_BORDER=.....
MATCH_CHAR=3
RIGHT_BORDER=.....
怎么样?看起来有点熟悉吧。这就是大多数计算机文献中语法定义的格式。
1.在python里,positive lookbehind assertion 只能匹配定长的字串,我看你给的连接里,没有说明,而且是.net的,没用过,所以有这么一问
2.我给的问题里,a和b之间的3是多于一个的,这也正是问题麻烦的地方。但是我没看出你的回答里是怎么解决的,能说明一下么?
要知道,问题里的例子只是为了说明问题,并不是要真的处理那个字串,而且我也只是觉得我自己的做法(类似铁手的)不够纯粹,想钻一下牛角尖而已。谢谢
如果零宽断言(Positive and Negative Lookahead)支持能变长匹配的话,如.NET,我上述的表达式可以匹配任意多的字符。考虑一下正则表达式的实现方法就明白了,其实我匹配的是‘3’,然后让正则引擎在找到‘3’这个字符之后去检查左右的边界是否符合要求,即两个零宽断言。由于左边界是a\w*——a开始的任意字符,右边界是\w*b——b结尾的任意字符。所以a开始和b结束之间的3都匹配。你可能被一般的搜索思路干扰了,正则表达式不是找到边界后去匹配边界中的字符,而是找到字符后去匹配边界。这就解释了第二个问题。
第一个问题就没办法解决了,你可以看看这个连接
外链出处,目前只有两个平台支持变长的匹配。
re.split("3(?=[^a]*b)", "132a43534b34a234234b345")
['132a4', '5', '4b34a2', '42', '4b345']
>>> re.split("3(?=[^a]*b)", "132a43534b34a234234b345b")
['132a4', '5', '4b34a2', '42', '4b', '45b']
最后一个3没在a和b中间,也给滤掉了
问题的逻辑比较清楚。先判断a出现后,然后直到b出现之前的3都不要,就可以了。
代码参见 http://paste.pocoo.org/show/134757/
我也贴在下面一份,不熟悉如何在西西河设置代码格式了。
def replace(line, start = 'a', end = 'b', source = '3', target = ''):
IN = False
for ch in line:
if ch == start:
if not IN:
IN = True
yield ch
elif ch == end:
if IN:
IN = False
yield ch
elif ch == source and IN:
yield target
else:
yield ch
def main():
line = '1234a5635367312b563789'
print ''.join(list(replace(line)))
if __name__ == "__main__":
main()
## output 1234a5656712b563789