Python的re,正则表达式,希望这次比较能让我记住里面的80%以上。(未完成,待继续)
re匹配www的url
'w{3}\.(?!-)[-A-Za-z0-9]{1,63}(?<!-)[.][A-Za-z]{2,}'
re(regex,regexp)是每个语言里面基本都会用到的,自己以前也一直看,看了忘,忘了看,希望这次写下博客,能够让自己思路清晰一点。
重点提醒,避坑:
使用Python原始字符串,建议再规则的地方前面加上r,禁止转义。
今天就上当了一个\b,\b在配制的时候,如果你默认啥参数不加,asci会匹配为退格符,你可以在\b之前再加\转义后面那个\实现你\b想要的效果。
但还是加r方便,这样的话,你再里面写什么都是re的规则,不用怕asci字符的影响,而且我测试了,好像也不影响\n的使用。建议没事就前面+r,禁止asci转义
首先,我先上re的模块函数:
re.compile:使用任何可选的标记来编译正则表达式的模式,然后返回一个正则表达式对象。(小提醒:re.compile里面设置了flags有效,通过re.compile后续进行查询,函数中的flags无效)
个人理解:生成一个re的pattern参数对象,使用后续我介绍的方法,该对象加函数,函数后面的参数里面pattren可以不用写。
re.compile的优势:能够提供预编译,预编译的话速度比较快,提升性能,所以进行多次比较操作,建议使用该函数。
re.pupge:清除隐式编译的正则表达式模式。因为模块函数会对已经编译的对象进行缓存,使用该方法可以进行缓存清除。
re.match(pattern,string,flags=0):从头部开始匹配字符串,如果匹配成功返回匹配对象,如果失败,就返回None。(只查找第一个)
re.saerch(pattern,string,flags=0):全文开始匹配字符串,如果匹配成功返回匹配对象,如果失败,就返回None。(只查找第一个)
参考链接:https://docs.python.org/zh-cn/3.8/howto/regex.html
这里有一个?!的特殊用法,用的很厉害,做个比较,有空可以回头来看
另一个零宽度断言是前向断言。 前向断言以正面和负面形式提供,如下所示:
(?=…)
-
正向前向断言。 如果包含的正则表达式,由
...
表示,在当前位置成功匹配,则成功,否则失败。 但是,一旦尝试了包含的表达式,匹配的引擎就不会前进;模式其余的部分会在在断言开始的地方尝试。 (?!…)
-
负向前向断言。 这与积正向断言相反;如果包含的表达式在字符串中的当前位置 不 匹配,则成功。
更具体一些,让我们看看前向是有用的情况。 考虑一个简单的模式来匹配文件名并将其拆分为基本名称和扩展名,用 .
分隔。 例如,在 news.rc
中,news
是基本名称,rc
是文件名的扩展名。
与此匹配的模式非常简单:
.*[.].*$
请注意,.
需要特别处理,因为它是元字符,所以它在字符类中只能匹配特定字符。 还要注意尾随的 $
;添加此项以确保扩展名中的所有其余字符串都必须包含在扩展名中。 这个正则表达式匹配 foo.bar
、autoexec.bat
、sendmail.cf
和 printers.conf
。
现在,考虑使更复杂一点的问题;如果你想匹配扩展名不是 bat
的文件名怎么办? 一些错误的尝试:
.*[.][^b].*$
上面的第一次尝试试图通过要求扩展名的第一个字符不是 b
来排除 bat
。 这是错误的,因为模式也与 foo.bar
不匹配。
.*[.]([^b]..|.[^a].|..[^t])$
当你尝试通过要求以下一种情况匹配来修补第一个解决方案时,表达式变得更加混乱:扩展的第一个字符不是 b
。 第二个字符不 a
;或者第三个字符不是 t
。 这接受 foo.bar
并拒绝 autoexec.bat
,但它需要三个字母的扩展名,并且不接受带有两个字母扩展名的文件名,例如 sendmail.cf
。 为了解决这个问题,我们会再次使模式复杂化。
.*[.]([^b].?.?|.[^a]?.?|..?[^t]?)$
在第三次尝试中,第二个和第三个字母都是可选的,以便允许匹配的扩展名短于三个字符,例如 sendmail.cf
。
模式现在变得非常复杂,这使得它难以阅读和理解。 更糟糕的是,如果问题发生变化并且你想要将 bat
和 exe
排除为扩展,那么该模式将变得更加复杂和混乱。
负面前向消除了所有这些困扰:
.*[.](?!bat$)[^.]*$
负向前向意味着:如果表达式 bat
此时不匹配,请尝试其余的模式;如果 bat$
匹配,整个模式将失败。 尾随的 $
是必需的,以确保允许像 sample.batch
这样的扩展只以 bat
开头的文件能通过。 [^.]*
确保当文件名中有多个点时,模式有效。
现在很容易排除另一个文件扩展名;只需在断言中添加它作为替代。 以下模块排除以 bat
或 exe
:
.*[.](?!bat$|exe$)[^.]*$
参考链接:https://docs.python.org/zh-cn/3.8/library/re.html#re.ASCII
(?=…)
-
匹配
…
的内容,但是并不消费样式的内容。这个叫做 lookahead assertion。比如,Isaac (?=Asimov)
匹配'Isaac '
只有在后面是'Asimov'
的时候。
(?!…)
-
匹配
…
不符合的情况。这个叫 negative lookahead assertion (前视取反)。比如说,Isaac (?!Asimov)
只有后面 不 是'Asimov'
的时候才匹配'Isaac '
。
(?<=…)
-
匹配字符串的当前位置,它的前面匹配
…
的内容到当前位置。这叫:dfn:positive lookbehind assertion (正向后视断定)。(?<=abc)def
会在'abcdef'
中找到一个匹配,因为后视会往后看3个字符并检查是否包含匹配的样式。包含的匹配样式必须是定长的,意思就是abc
或a|b
是允许的,但是a*
和a{3,4}
不可以。注意以 positive lookbehind assertions 开始的样式,如(?<=abc)def
,并不是从 a 开始搜索,而是从 d 往回看的。你可能更加愿意使用search()
函数,而不是match()
函数:>>> import re >>> m = re.search('(?<=abc)def', 'abcdef') >>> m.group(0) 'def'
这个例子搜索一个跟随在连字符后的单词:
>>> m = re.search(r'(?<=-)\w+', 'spam-egg') >>> m.group(0) 'egg'
在 3.5 版更改: 添加定长组合引用的支持。
(?<!…)
-
匹配当前位置之前不是
...
的样式。这个叫 negative lookbehind assertion (后视断定取非)。类似正向后视断定,包含的样式匹配必须是定长的。由 negative lookbehind assertion 开始的样式可以从字符串搜索开始的位置进行匹配。
今天总算有空可以看一下re,顺便翻了一下《Python核心编程》,书中内容还是非常不错的,只怪当年水平有限制没有看.
主要讲一些我对?= ?! ?<= 与?<!的一些理解,上面的是Python官网给的说明,示例比较少,我花了点时间,现在至少理解了。
首先这些只不过是放在匹配中的一些条件,单完全不会显式在匹配的信息中。
In [223]: re.search(r'(?=-)-egg', 'spam-egg') Out[223]: <re.Match object; span=(4, 8), match='-egg'>
我拿了官网的demo改了一下儿,很明显只有满足有-的条件才开始匹配,而且匹配点是从条件的满足点开始的。
理解了这个点,?<=属于先找出符合的条件,再向右边进行适配。
In [230]: re.search('123abc(?<=abc)def', '123abcdef') Out[230]: <re.Match object; span=(0, 9), match='123abcdef'> In [231]: re.search('(?<=abc)def', 'abcdef') Out[231]: <re.Match object; span=(3, 6), match='def'>
一个是从从左往右进行适配,一个是从右往左进行适配,虽然理解了具体的规则,但使用的话,还要进行多的锻炼