2.正则表达式使用基础:量词(一)

2019-08-10  本文已影响0人  BoatingTao

2.1 一般形式

  1. 上一节我们了解到字符组 [0-9] 或 \d 可以匹配单个数字字符。现在我们使用正则来验证更复杂的字符串,比如国内邮政编码。很自然,\d 匹配单个字符,那么我们可以这样写:
  re.search(r"^\d\d\d\d\d\d$", "110016")  !=None   # => True
  1. 这样写的话,太麻烦了, \d 重复了6次,不够灵活方便。为此,正则表达式提供了量词,上面的匹配格式可以简写为 \d{6}。意思就是 匹配 6个数字。

    下面举几个简单的例子:

   re.search(r"^\d{6}$", "100861") !=None  # => True

   re.search(r"^\d{6}$", "1A0861") !=None  # => False
  1. 量词还可以不确定长度,通用形式是 {m,n},注意中间逗号后面不跟空格。它限定之前的元素能够出现的次数,m是下线,n是上限。均为闭区间。\d{4,6},表示这个数字字符的长度最短是4个字符,最长是6个字符。

    量词的限定出现次数一般都有明确下限,如果没用,则默认为0。有些语言可以省略0,写作 {,n},但是这样不是通用的,建议写作 {0,n}。

    下表展示了量词的一般书写形式:

2.2 常用量词

  1. {m,n} 是通用形式上的量词,正则表达式还有3个常用量词,分别是 +、?、*,它们的形态虽不同于 {m,n},但是功能也相同,可以看作是量词的简记法。

  2. 常用量词书写形式:

大部分情况下只需要表示上面这三种意思,所以常用量词的使用频率高于 {m,n},例子如下:匹配 traveler 和 traveller (美式和英式)

re.search(r"^traverll?er", "traveler") !=None  # =>True

re.search(r"^traverll?er", "traveler") !=None  # =>True

量词也广泛用于解析HTML代码,匹配各种标签及标签中的内容。例如匹配所有 html tag的正则表达式:<[^>]+>;匹配 open tag , <[/][>]*>;匹配 close tag ,</[^>]+>;匹配 self-closing tag,<[^>/]+/>

2.3 数据提取

  1. 之前使用的python正则查询函数都是 search(),如果匹配成功,返回一个MatchObject的对象,这个对象包含了匹配的信息,比如匹配的结果。可以使用
re.search(r"^traverll?er", "traveler").group(0)  来获取匹配结果。
  1. 这里再介绍一个python的方法,findall(pattern,string),如果匹配成功,返回的是一个数组。例如:使用findall()来匹配两个邮政编码。注意:search 和 findall 都是python正则表达式库的函数,其他语言不一样。
re.findall(r"\d{6}", "zipcode1:123456, zipcode2:987654")

得到的结果就是 ['123456', '987654'],注意这里我们需要匹配6个数字,所以不需要在正则表达式外面加上 开始 和 $结尾来限定。

2.4 点号

  1. 上一章提到过, "." 号可以匹配任意字符,但是换行符 \n 这种不能匹配。要匹配任意字符可以 [\w\W] 这种。因为点号几乎可以匹配任意字符,所以实际运用中很多人图省事,随意使用 .* 或者 .+ ,结果却事与愿违。下面我们看一个例子:

    我们希望匹配的字符串内容是 "quoted string",待匹配的字符串也是 "quoted string" ,注意这里匹配包含前后双引号。我们这样写没问题:

re.search(r"\".*\"","\"quoted string\"").group(0)   # =>   "quoted string"   
  1. 这样得到的结果没问题,那么我们再变一下。现在我们改变一下待匹配字符串,"quoted string" and another",然后我们用同样的 pattern 去匹配这一段字符串,得到的结果却是 "quoted string" and another",这个结果不是我们想要的 "quoted string" 。

至于 "quoted string" and another" 也是一样的道理,最开始 .* 匹配了 字符串 * 后的所有内容,后来发现正则中还有 " 未匹配,因此回溯最近的 一个 " ,交给匹配字符李的 " 进行匹配。

image.png
  1. 因此要准确匹配 "quoted string" and another" 字符串中的 "quoted string" ,就不能图省事使用 "." 来匹配,需要使用 "[^"]"
    image.png

2.5 忽略优先量词

  1. 但某些时候,也会需要使用到 .* 匹配,比如匹配 <script type="text/javascript">...</script> ,script标签左右的开关标签好写, 但是js内部的代码可以出现任意字符,所以这个时候还是得 用 .* 来匹配。.* 不能匹配换行符,所以这里用 [\s\S]* 来匹配。
str1 =  """
    <script type="text/javascript">
    alert("1");
    </script>
    <br />
    <script type="text/javascript">
    alert("2");
    </script>
"""
print(re.search(r"<script type=\"text/javascript\">[\s\S]*</script>",str1).group(0))
输出 image.png
re.search(r"<script type=\"text/javascript\">[\s\S]*?</script>",str1)

再 * 后面增加了 一个 ? 号。这样就能提取出所有 js标签及代码。
匹配优先量词与忽略优先量词逐一对应。所有的匹配优先量词后加 ? 即可。
例如 * 对应 *? 。

忽略优先量词可以提取 c 语言中的护士、提取网页中超链接tag、解析表格等。

print(re.search(r"^.*/"), "/usr/local/bin/pyhton")

2.6 转义

上一篇 下一篇

猜你喜欢

热点阅读