西西河

主题:文问题,关于正则表达式 -- pastebt

共:💬26 🌺8 新:
全看树展主题 · 分页首页 上页
/ 2
下页 末页
家园 单用正则好像是搞不定这件事

正则语言比普通语言好像是差了什么功能,记得有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都匹配。你可能被一般的搜索思路干扰了,正则表达式不是找到边界后去匹配边界中的字符,而是找到字符后去匹配边界。这就解释了第二个问题。

第一个问题就没办法解决了,你可以看看这个连接

外链出处,目前只有两个平台支持变长的匹配。

家园 谢谢,在python里面也弄出来了

re.split("3(?=[^a]*b)", "132a43534b34a234234b345")

['132a4', '5', '4b34a2', '42', '4b345']

家园 这个有BUG吧?

>>> 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

关键词(Tags): #Python
全看树展主题 · 分页首页 上页
/ 2
下页 末页


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河