美文网首页
正则表达式 特殊构造用法

正则表达式 特殊构造用法

作者: 大富帅 | 来源:发表于2016-07-26 16:13 被阅读114次

查找不能有某个字符串的正则匹配

^((?!hede).)*$
^(?!.*hede).*$

^((?!hede).)*$ 解释:

表达式(?!hede).会往前查找,看看前面是不是没有“hede”字串,如果没有(是其它字符),那么.(点号)就会匹配这些其它字符。这种正则表达式的“查找”也叫做“zero-width-assertions”(零宽度断言),因为它不会捕获任何的字符,只是判断。

在上面的例子里,每个空字符都会检查其前面的字符串是否不是‘hede’,如果不是,这.(点号)就是匹配捕捉这个字符。表达式(?!hede).只执行一次,所以,我们将这个表达式用括号包裹成组(group),然后用*(星号)修饰——匹配0次或多次:((?!hede).)**。

你可以理解,正则表达式((?!hede).)*匹配字符串"ABhedeCD"的结果false,因为在e3位置,(?!hede)匹配不合格,它之前有"hede"字符串,也就是包含了指定的字符串。

在正则表达式里, ?! 是否定式向前查找,它帮我们解决了字符串“不包含”匹配的问题。

^(?!.*hede).*$ 解释

在这种情况下我们使用 ^(?!.*hede).*$ 正则表达式 我们将第一个.*移到了零宽度断言的里面。在匹配的时候首先匹配行首的位置,然后接下来是匹配行首后面的位置,要求此位置的后面不能是 .*hede 匹配的字符串,说白了要求此位置的后面不能是xxxxxxxxxxxxxxxxxxhede 类似的字符串,这样就排除了从行首开始后面含有hede的情况了。

延伸的问题:

问题:查找有多个<img>标签的文本, img 与src 之间不能emoji 出现的标签
方案1: 方案1 demo

 # reg_pattern = r'<img(?!.*emoji).*?src="([^"!"]*?\.(gif|png|jpg|webp))!?(.*?)".*?>'

方案1 解释:
本来是想找到img src之间不能有emoji ,根据字符串不能出现某个字符串的正则写法
^(?!.*helloworld).*$ 所以我写成了 <img(?!.emoji).?src 这样,本想着这样可以,但是问题是多个img标签都是在同一个字符串里面,结果变成了 img 到最后src 之间不能有emoji ,所以中间的所有img都匹配不上了! 而且我的写法 .?src 已经是非贪婪模式,还是因为这个(?!.emoji) 变成了贪婪模式

方案二: 方案二 demo

#reg_pattern = r'<img(?![^"]*emoji)[^"]+?src="([^"!"]*?\.(gif|png|jpg|webp))!?(.*?)".*?>'

方案2 解释:由方案一我想到,我的需求是(?!.emoji)不要贪婪模式,然后看了资料写成(?![^"]emoji)以为在(?!)再写条件就可以避免贪婪, 结果原来这种写法是不行的,真正起作用的是 [^"]+?src 要求src前面不能有" 而我们的字符串刚好是防止前面有class="emoji" 恰巧有" 所以看上去才貌似起了不贪婪的作用, 其实(?![^"]*emoji) 不起作用的

最终方案: 最后方案 demo

reg_pattern = r'<img((?!emoji).)*?src=\"([^\"!]*?\.(gif|png|jpg|webp))!?([^\"]*?)\"((?!emoji).)*?>'

解释:看上面 ^(?!.hede).$ 解释

总结:

利用正则排除某字符串的方式有两种:

  • ^(?!.helloworld).$
  • ^((?!helloworld).)*$
    区别是:
    第一种相当于贪婪的模式, 整个字符串不能出现
    第二种可以作为非贪婪模式的补充,限定不能出现的范围


问题: 查找不能有字符串abc的匹配

正则表达式 字符串 结果
r'a(?=bbb)' abbb a
r'abbb' abbb abbb

python 2.7 文档说明 https://docs.python.org/2/library/re.html

(?=...)
Matches if ... matches next, but doesn’t consume any of the string. This is called a ** lookahead assertion **. For example, Isaac (?=Asimov) will match 'Isaac ' only if it’s followed by 'Asimov'.
(?!...)
Matches if ... doesn’t match next. This is a negative lookahead assertion. For example, Isaac (?!Asimov) will match 'Isaac ' only if it’s not followed by 'Asimov'.

** (?=) 可以看出这种形式的作用是判断条件不计入匹配结果,仅仅是判断条件**

(?<=...) **Group references are not supported ** even if they match strings of some fixed length. Note that patterns which start with positive lookbehind assertions will not match at the beginning of the string being searched;

** 说明(?) 里匹配到的内容都不能使用组引用比如\1 \g<1>引用对应的内容**

同理re.sub, re.search的替换也同样适合这种原理

tmp = 'abbb'
s = re.sub(r'a(bbb)', 'accc', tmp) # 整个匹配规则替换
# 结果
accc

s = re.sub(r'a(?=bbb)', 'accc', tmp) # (?=)里面的内容只做判断作用,不作为匹配结果,所以需要匹配某个规则,又不需要整个规则替换,可以用这个模式
# 结果
acccbbb

s = re.sub(r'a(?=bbb)', 'accc\g<1>', tmp)
# 报错:invalid group reference 不是匹配结果,所以不能引用

s = re.sub(r'a(bbb)', 'accc\g<1>', tmp)
# 正常可以引用 
# 结果
acccbbb

s = re.findall(r'a(?=bbb)', 'abbb')
# 结果  不是匹配结果,所以不能引用
 ['a'] 

继续深入(?=)用法

re.findall('a(?=bhc)d', 'abhcd')
所以这个表达式的意思是:
a后边的表达式必须是bhc, 后面是d
结果: []

为什么? 因为这个(?=bhc)只是针对a后面的匹配, 不是针对d前面的,而对d来说,前面其实是没有匹配表达式
SO, d前面必须是a, 而a后面又必须时bhc,所以永远匹配不到任何东西
应该改成这样:
re.findall('a(?=bhc)\w*d', 'abhcd')
结果: ['abhcd']

分组引用问题

s = re.sub(r'a(?P<hello>xyz)', 'xx\g<hello>', 'axyz') # 使用组名引用 

s = re.sub(r'a(xyz)', 'hello \g<1>', 'axyz')  # 使用序号引用

s = re.sub(r'a(xyz)', 'hello \1', 'axyz')  # 乱码

使用组名或者序号\g<1>来引用是没问题的,但是\1 \2引用会出问题 , 查了下资料,直接用\1这种引用的话,如果后面也是数字比如\10就会引用到第10组,所以避免歧义,还是用\g<1>这种吧

(?=) (?!) 实例:

image.png
title = re.sub(r'span\s+style\s*=\s*".*?color:\s*(.*?)[;"].*?>(.*?)</span>', 'font color="\g<1>">\g<2></font>', title)
# \1 \2 不行 要用\g<1>
#  .*?color 是非贪婪模式, .*是匹配所有字符,但是到color就不要匹配,因为非贪婪模式

# 去掉所有非span, strong 的标签
# eg  : a = '<span><p><strong> hello world </p> </strong> </span>'
# 执行后 被去掉了<p></p> 结果是:<span><strong> hello world  </strong> </span>
title = re.sub(r'</?((?!span|strong).)*?>', '', title)   

# 去掉换行和空格, 这里的换行可能要加上\r\n
title = re.sub(r'\n| ', '', title)

title = re.sub(r'color="(.*?)"', color_formater, title)
title = re.sub(r'</?(span).*?>', '', title)
  • 重点讲解
title = re.sub(r'</?((?!span|strong).)*?>', '', title) 

文章上面也有解析相关知识
</?((?!span).)*?> 这里可以拆开几个步骤:

  1. (?!span) 只是针对</ 这个匹配,意思是</ 后面不需不能是span
  2. 对于((?!span).)的 . 其实是可以匹配任何东西的,但是前面第一步说了</必须不能是span, 这样实际上就限定了. 不能是任何东西,只能是非span
  3. 那么((?!span).) 其实是可以看成 (.)*? 普通的组匹配,只不过组里面不能是span
  4. (.)?> 实际上可以看成.?> 非贪婪模式 匹配最近的一个> 结束符

参考:http://www.cnblogs.com/deerchao/archive/2007/02/15/651411.html

正则匹配换行符

需求: 将占位符[photo_0] [photo_1] .. 以及他们后面的换行符,一起替换成图片<img>,所以就需要匹配到换行符, 而换行符可能时\r 、\n 、\r\n 同时存在。做的时候只考虑了\n导致一致匹配不上!

ms_content = re.sub(r'\[photo_(\d+)\](\r\n|\r|\n)?', img_replace_func, content)

def img_replace_func(m):
    """替换图片用到的函数re.sub
        global upload_url_list
    """
    try:
        index = int(m.group(1))
        url = cdn_essay_upload_img_list[index]
        img_html = '' % url
        return img_html
    except Exception, e:
        return ''

相关链接 http://www.cnblogs.com/wangqiguo/archive/2012/05/08/2486548.html

findall VS search VS match 的区别

# 查找所有img标签
 match = re.findall(r'(<img.*?src=(".*?")(.*?)>)', full_content)

src=".?" 是典型的非贪婪模式, 匹配最近的" 也就是匹配src里面的内容
.
?> 也是同样道理,匹配最近的> 也就是整个img 标签的结束

一开始想着用re.search来做, 但是查了以后,search 和 match 都是只匹配一个, 区别是match只从开头匹配, search可以再字符串任意位置匹配。 但是他们的特点是: 只匹配一次!
所以我要想找所有的img标签, 用search就不合适了。 search找出来的group(0, 1, 2)都是针对一个匹配里面的子匹配!而不是多个匹配!

这里要用findall, 返回所有列表

相关文章

  • 正则表达式 特殊构造用法

    查找不能有某个字符串的正则匹配 ^((?!hede).)*$^(?!.*hede).*$ ^((?!hede).)...

  • 正则表达式特殊符号及用法

    Python3 正则表达式特殊符号及用法(详细列表) 正则表达式的强大之处在于特殊符号的应用,特殊符号定义了字符集...

  • 正则

    正则表达式 创建正则表达式 使用一个正则表达式字面量 调用 RegExp 对象的构造函数 特殊字符 ^ 匹配输入的...

  • Python正则表达式用法详解

    搞懂Python 正则表达式用法 Python 正则表达式 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一...

  • java06(关键字this,关键字static,静态代码块,m

    关键字this: 基础用法:老夫认为语法同js,没有什么需要记录的。 特殊用法:位于构造函数中的第...

  • 一文学会正则表达式

    正则表达式是编程中常用的校验和过滤字符的手段,本文主要讲解 正则表达式基础、一些特殊用法和常用到的正则表达式案例。...

  • Python 学习笔记 070

    正则表达式学习 续3 语言注释的正则识别及解释 C语言为例 正则表达式的特殊用法 re.split()工具 pyt...

  • Python正则表达式初识(四)

    今天继续给大家分享Python正则表达式基础知识,主要给大家介绍一下特殊字符“{}”的用法,具体的教程如下。 特殊...

  • 正则表达式

    正则表达式创建方式 字面量 构造函数 特殊字符 与正则对象相关的属性 你可以使用一个正则表达式创建一个没有分配给变...

  • flutter Switch组件

    构造方法 用法

网友评论

      本文标题:正则表达式 特殊构造用法

      本文链接:https://www.haomeiwen.com/subject/dewnjttx.html