python使用正则匹配判断字符串中含有某些特定子串及正则表达式详解
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、判断字符串中是否含有字串</a></li><li><a href="#_label1">二、正则表达式</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">(一)基本内容</a></li><ul class="third_class_ul"><li><a href="#_label3_1_0_0">1.正则表达式修饰符——可选标志</a></li><li><a href="#_label3_1_0_1">2.正则表达式模式</a></li></ul><li><a href="#_lab2_1_1">(二)常见表达式函数</a></li><ul class="third_class_ul"></ul></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、判断字符串中是否含有字串</h2><p>1. <code>in</code>,<code>not in</code></p>
<p>判断字符串中是否含有某些关键词,方法比较多<br />例如分词后对词向量和关键词进行<code>==</code>匹配,但这种方法以来分词的准确性,不太推荐;<br />其次使用成员运算符<code>in</code>,<code>not in</code>可以较好的判断字符串中是否包含某关键词,即特定字串</p>
<div class="jb51code"><pre class="brush:py;">a = '这个暑假我读了红楼梦和三国演义'
b= ['三国演义','水浒传','西游记','红楼梦']
n = 0
for i in b:
if i in a:
n += 1
print(f'四大名著暑假读了{n}本')</pre></div>
<p>这种遍历算法虽然可以成功得到想要的结果,但是当数据量很大的时候,程序执行效率将会很低。正则匹配作为专业的查找工具,在判断字符串中含有特定字串的事情上可以大大提高工作效率。</p>
<p>2.正则匹配<code>re.findall</code></p>
<div class="jb51code"><pre class="brush:py;">import re
def is_in(fullstr,substr):
if re.findall(substr,fullstr):
return 1
else:
return 0
a = '这个暑假我读了红楼梦和三国演义'
b= ['三国演义','水浒传','西游记','红楼梦']
n = 0
for i in b:
n = is_in(a,i)
n += 1
print(f'四大名著暑假读了{n}本')</pre></div>
<p><code>findall</code>:返回string中所有与pattern匹配的全部字符串,返回形式为数组</p>
<div class="jb51code"><pre class="brush:py;">re.findall(pattern, string, flags=0)</pre></div>
<p>示例如下:</p>
<div class="jb51code"><pre class="brush:py;">line = []
n = 0
for i in b:
num = is_in(a,i)
n += num
res = re.findall(i,a)
line = line + res
print(f'四大名著暑假读了{n}本')
print(f'分别是{line}')
'''
res = re.findall(i,a) re.findall返回值是一个列表
out:
四大名著暑假读了2本
分别是['三国演义', '红楼梦']
'''</pre></div>
<p>正则的功能十分强大,上述使用的只是其中一个很小的功能。下面继续对正则的强大功能进行学习</p>
<p class="maodian"><a name="_label1"></a></p><h2>二、正则表达式</h2>
<p class="maodian"><a name="_lab2_1_0"></a></p><h3>(一)基本内容</h3>
<p class="maodian"><a name="_label3_1_0_0"></a></p><h4>1.正则表达式修饰符——可选标志</h4>
<p>正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志</p>
<table><thead><tr><th>修饰符</th><th>功能</th><th>全称</th></tr></thead><tbody><tr><td>re.I</td><td>匹配忽略大小写</td><td>re.IGNORECASE</td></tr><tr><td>re.L</td><td>做本地化识别(locale-aware)匹配,即表示特殊字符集 <code>\w</code>, <code>\W</code>, <code>\b</code>, <code>\B</code>, <code>\s</code>, <code>\S</code> 依赖于当前环境(<strong>该标记官方已经不推荐使用</strong>)</td><td>re.LOCALE</td></tr><tr><td>re.M</td><td>多行匹配,影响<code> ^</code> 和<code> $</code>(正则表达式中<code>^</code>表示匹配行的开头,默认模式下它只能匹配字符串的开头;而在多行模式下,它还可以匹配 换行符<code>\n</code>后面的字符。<strong>NOTE</strong>:正则语法中<code>^</code>匹配行开头、<code>\A</code>匹配字符串开头,单行模式下它两效果一致,多行模式下<code>\</code>A不能识别<code>\n</code>)</td><td>re.MULTILINE</td></tr><tr><td>re.S</td><td>使·<code>. </code>匹配包括换行在内的所有字符(DOT表示.,ALL表示所有,连起来就是<code>.</code>匹配所有,包括换行符<code>\n</code>。默认模式下<code>.</code>是不能匹配行符<code>\n</code>的)</td><td>re.DOTALL</td></tr><tr><td>re.U</td><td>表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库(与 ASCII 模式类似,匹配unicode编码支持的字符,但是 <strong>Python 3 默认字符串已经是Unicode</strong>,所以有点<strong>冗余</strong>)</td><td>re.UNICODE</td></tr><tr><td>re.X</td><td>增加可读性,忽略空格和 # 后面的注释 (默认模式下并不能识别正则表达式中的注释,而详细模式是可以识别的)</td><td>re.VERBOSE</td></tr><tr><td>re.A</td><td>让 \w, \W, \b, \B, \d, \D, \s 和 \S 只匹配ASCII,而不是Unicode</td><td>re.ASCII</td></tr><tr><td>re.DEBUG</td><td>显示编译时的debug信息</td><td>re.DEBUG</td></tr></tbody></table>
<p class="maodian"><a name="_label3_1_0_1"></a></p><h4>2.正则表达式模式</h4>
<p>模式字符串使用特殊的语法来表示一个正则表达式:<br />(1)字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。<br />(2)多数字母和数字前加一个反斜杠时会拥有不同的含义,例如<code>\n </code>表示换行。<br />(3)标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。<br />(4)反斜杠本身需要使用反斜杠转义。<br />(5)由于正则表达式通常都包含反斜杠,所以最好使用原始字符串来表示它们。模式元素(如 <code>r'\t'</code>,等价于 <code>'\\t'</code>)匹配相应的特殊字符。</p>
<p>下表列出了正则表达式模式语法中的特殊元素。如果使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。</p>
<table><thead><tr><th>模式</th><th>功能</th><th>示例</th><th>匹配的字符串</th></tr></thead><tbody><tr><td><code>^</code></td><td>匹配字符串的开头</td><td></td><td></td></tr><tr><td><code>$</code></td><td>匹配字符串的结尾</td><td></td><td></td></tr><tr><td><code>.</code></td><td>匹配任意字符,除了换行符<code>\n</code></td><td></td><td></td></tr><tr><td><code>[…]</code></td><td>表示一组字符单独列出</td><td><code></code></td><td><code>'l'</code>,<code>'i'</code>,<code>'k' 'e'</code></td></tr><tr><td><code>[^…]</code></td><td>表示不在[]中的字符</td><td><code>[^like]</code></td><td>除了<code>'l'</code>,<code>'i'</code>,<code>'k'</code> ,<code>e</code>之外的字符</td></tr><tr><td><code>\w</code></td><td>匹配字母数字及下划线</td><td><code>a-z</code>、<code>A-Z</code>、<code>0-9</code>、<code>_</code></td><td></td></tr><tr><td><code>\W</code></td><td>匹配非字母数字及下划线</td><td></td><td></td></tr><tr><td><code>\s</code></td><td>匹配任意空白字符,等价于<code> \t</code> <code>\n</code> <code>\r</code> <code>\f</code></td><td></td><td></td></tr><tr><td><code>\S</code></td><td>匹配任意非空字符</td><td></td><td></td></tr><tr><td><code>\d</code></td><td>匹配任意数字,等价于 </td><td></td><td></td></tr><tr><td><code>\D</code></td><td>匹配任意非数字</td><td></td><td></td></tr><tr><td><code>\A</code></td><td>匹配字符串开始</td><td></td><td></td></tr><tr><td><code>\z</code></td><td>匹配字符串结束</td><td></td><td></td></tr><tr><td><code>\Z</code></td><td>匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串</td><td></td><td></td></tr><tr><td><code>\G</code></td><td>匹配最后匹配完成的位置</td><td></td><td></td></tr><tr><td><code>\b</code></td><td>匹配一个单词边界,也就是指单词和空格间的位置</td><td><code>er\b</code></td><td><code>never</code> (√),<code>verb</code>(×)</td></tr><tr><td><code>\B</code></td><td>匹配非单词边界</td><td><code>er\b</code></td><td><code>never</code> (×),<code>verb</code>(√)</td></tr><tr><td><code>\n</code> <code>\t</code>等</td><td>匹配一个换行符。匹配一个制表符。等</td><td></td><td></td></tr><tr><td><code>\1</code> …<code>\9</code></td><td>匹配第n个分组的内容</td><td></td><td></td></tr><tr><td><code>\10</code></td><td>匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式</td><td></td><td></td></tr><tr><td><code>re*</code></td><td>(<code>*</code> 贪婪)匹配0个或多个表达式(前一个字符出现0次或者⽆限次,即可有可⽆)</td><td><code>abc*</code></td><td><code>abccc</code></td></tr><tr><td><code>re+</code></td><td>(<code>+</code>懒惰)匹配1个或多个的表达式(前一个字符出现1次或者⽆限次,即⾄少有1次)</td><td><code>abc+</code></td><td><code>abc</code> <code>abcccc</code></td></tr><tr><td><code>re?</code></td><td>(<code>?</code>占有)匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式(前一个字符出现1次或者0次,即要么有1次,要么没有)</td><td><code>abc?</code></td><td><code>abc</code> <code>ab</code></td></tr><tr><td><code>re{n}</code></td><td>前一个字符出现n次</td><td><code>o{2}</code></td><td><code>food</code></td></tr><tr><td><code>{m,n}</code></td><td>匹配前⼀个字符出现从m到n次,若省略m,则匹配0到n次,若省略n,则匹配m到无限次</td><td><code>ab{1,2}c</code></td><td><code>abc</code> <code>abbc</code></td></tr><tr><td><code>a |b</code></td><td>匹配a或b</td><td></td><td></td></tr><tr><td><code>(re)</code></td><td>对正则表达式分组并记住匹配的文本</td><td></td><td></td></tr><tr><td><code>\num</code></td><td>引⽤分组num匹配到的字符串</td><td></td><td></td></tr><tr><td><code>(?P<name>)</code></td><td>分组起别名,匹配到的子串组在外部是通过定义的 name 来获取的</td><td></td><td></td></tr><tr><td><code>(?P=name)</code></td><td>引⽤别名为name分组匹配到的字符串</td><td></td><td></td></tr></tbody></table>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>(二)常见表达式函数</h3>
<p>正则表达式是一个特殊的字符序列,可以方便的检查一个字符串是否与某种模式匹配,python自带的<code>re</code>模块使 Python 语言拥有全部的正则表达式功能<br />python常用的正则表达式函数如下:</p>
<table><tbody><tr><th>功能分类</th><th colspan="3">函数</th><th colspan="3">功能</th></tr><tr><td rowspan="3"><p>查找一个匹配项</p></td><td colspan="3"><p>re.search</p></td><td colspan="3"><p>查找任意位置的匹配项</p></td></tr><tr><td colspan="3"><p>re.match</p></td><td colspan="3"><p>必须从字符串开头匹配</p></td></tr><tr><td colspan="3"><p>re.fullmatch</p></td><td colspan="3"><p>整个字符串与正则完全匹配</p></td></tr><tr><td rowspan="2"><p>查找多个匹配项</p></td><td colspan="3"><p>re.findall</p></td><td colspan="3"><p>从字符串任意位置查找,返回一个列表</p></td></tr><tr><td colspan="3"><p>re.finditer</p></td><td colspan="3"><p>从字符串任意位置查找,返回一个迭代器</p></td></tr><tr><td rowspan="1"><p>分割</p></td><td colspan="3"><p>re.split</p></td><td colspan="3"><p>用正则表达式将某字符串分割成多段</p></td></tr><tr><td rowspan="2"><p>替换</p></td><td colspan="3"><p>re.sub</p></td><td colspan="3"><p>替换掉某字符串中被正则表达式匹配的字符,返回替换后的字符串,替换可以是字符串 也可以是 函数</p></td></tr><tr><td colspan="3"><p>re.subn</p></td><td colspan="3"><p>替换掉某字符串中被正则表达式匹配的字符,返回替换后的字符串 和 替换次数</p></td></tr><tr><td rowspan="2"><p>编译正则对象</p></td><td colspan="3"><p>re.compile</p></td><td colspan="3"><p>将正则表达式的样式编译为一个 正则表达式对象 (正则对象Pattern)</p></td></tr><tr><td colspan="3"><p>re.template</p></td><td colspan="3"><p>将正则表达式的样式编译为一个 正则表达式对象 ,并添加re.TEMPLATE模式</p></td></tr><tr><td rowspan="2"><p>其他</p></td><td colspan="3"><p>re.escape</p></td><td colspan="3"><p>可以转义正则表达式中具有特殊含义的字符,比如: . 或者 *</p></td></tr><tr><td colspan="3"><p>re.purge</p></td><td colspan="3"><p>清除正则表达式缓存</p></td></tr></tbody></table>
<p>1. <code>re.match</code></p>
<p><code>re.match</code> 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回 none</p>
<div class="jb51code"><pre class="brush:py;">re.match(pattern, string, flags=0)</pre></div>
<p></p>
<table><tbody><tr><th>参数</th><th>说明</th></tr><tr><td>pattern</td><td>匹配的正则表达式</td></tr><tr><td>string</td><td>要匹配的字符串</td></tr><tr><td>flags</td><td>标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。详见表1修饰符</td></tr></tbody></table>
<p>匹配成功 <code>re.match </code>方法返回一个匹配的对象,否则返回 None<br />可以使用 <code>group(num)</code> 或 <code>groups() </code>匹配对象函数来获取匹配表达式</p>
<table><tbody><tr><th>匹配对象方法</th><th>描述</th></tr><tr><td>group(num=0)</td><td>匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组</td></tr><tr><td>groups()</td><td>返回一个包含所有小组字符串的元组,从 1 到 所含的小组号</td></tr></tbody></table>
<p>0:表示正则表达式中符合条件的字符串。<br />1:表示正则表达式中符合条件的字符串中的第一个() 中的字符串。<br />2:表示正则表达式中符合条件的字符串中的第二个() 中的字符串。<br />以此类推…</p>
<div class="jb51code"><pre class="brush:py;">import re
fullstr = 'name:alice,result:89'
result = re.match('name:(\w+),result:(\d+)', fullstr)
print(result)
print(result.group(0))
print(result.group(1))
print(result.group(2))
print(result.group())</pre></div>
<p>结果:</p>
<blockquote><p>out1: <re.Match object; span=(0, 20), match=‘name:alice,result:89’><br />out2: name:alice,result:89<br />out3: alice<br />out4: 89<br />out5: name:alice,result:89</p></blockquote>
<p>从结果可以看出,re.match()方法返回一个匹配的对象,而不是匹配的内容。通过调用span()可以获得匹配结果的位置。而如果从起始位置开始没有匹配成功,即便其他部分包含需要匹配的内容,re.match()也会返回None<br />可以使用<code>group()</code>来提取每组匹配到的字符串。<br />group()会返回一个包含所有小组字符串的元组,从 0 到 所含的小组号</p>
<p><strong>注意</strong>:如果在运用正则表达式做匹配的过程中没有匹配到元素,之后又调用了group(),会报错:<code>AttributeError: 'NoneType' object has no attribute 'group'</code><br />如果出现这种报错,可以将match改成search()就可以避开这类问题了。search函数是先扫描全部的代码块,再进行提取的</p>
<p>2.<code>re.search</code></p>
<p>re.search会匹配整个字符串,并返回第一个成功的匹配。如果匹配失败,则返回None</p>
<div class="jb51code"><pre class="brush:py;">re.search(pattern, string, flags=0)</pre></div>
<p>参数同<code>re.match</code></p>
<p>示例:</p>
<div class="jb51code"><pre class="brush:py;">import re
fullstr = 'class:1班,name:alice,result:89'
result = re.match('name:(\w+),result:(\d+)', fullstr)
print(result)
print(result.group(0))</pre></div>
<blockquote><p>out1: None<br />out2: AttributeError: ‘NoneType’ object has no attribute ‘group’<br />原因:match在起始位置匹配,如果不是起始位置匹配成功的话,match() 就返回 none</p></blockquote>
<p>尝试<code>search</code></p>
<div class="jb51code"><pre class="brush:py;">import re
fullstr = 'class:1班,name:alice,result:89'
result = re.search('name:(\w+),result:(\d+)', fullstr)
print(result)
print(result.group(0))
print(result.group(1))
print(result.group(2))
print(result.group())</pre></div>
<blockquote><p>out1: <re.Match object; span=(9, 29), match=‘name:alice,result:89’><br />out2: name:alice,result:89<br />out3: alice<br />out4: 89<br />out5: name:alice,result:89</p></blockquote>
<p>3. <code>re.sub</code></p>
<p>该函数主要用于替换字符串中的匹配项</p>
<div class="jb51code"><pre class="brush:py;">re.sub(pattern, repl, string, count=0, flags=0)</pre></div>
<p>示例如下:</p>
<table><thead><tr><th>参数</th><th>说明</th></tr></thead><tbody><tr><td>pattern</td><td><strong>必须参数</strong>:正则中的模式字符串</td></tr><tr><td>repl</td><td><strong>必须参数</strong>:替换的字符串,也可为一个函数</td></tr><tr><td>string</td><td><strong>必须参数</strong>,要被查找替换的原始字符串</td></tr><tr><td>count</td><td>可选参数,模式匹配后替换的最大次数,默认 0 表示替换所有的匹配</td></tr><tr><td>flags</td><td>可选参数,表示编译时用的匹配模式(如忽略大小写、多行模式等),数字形式,默认为0</td></tr></tbody></table>
<div class="jb51code"><pre class="brush:py;">#修改分数
fullstr = 'name:alice,result:89'
res1 = re.sub(r'\d+','90',fullstr)
print(res1)</pre></div>
<blockquote><p>out: name:alice,result:90</p></blockquote>
<p><code>repl</code>可以为一个函数。如下:</p>
<div class="jb51code"><pre class="brush:py;">#修改分数
def change(matched):
value = int(matched.group('value'))
return str(value + 1)
fullstr = 'name:alice,result:89'
res1 = re.sub('(?P<value>\d+)',change,fullstr)
print(res1)</pre></div>
<blockquote><p>out: name:alice,result:90</p></blockquote>
<p>4.<code>re.compile</code></p>
<p>compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用<br />re 模块的一般使用步骤是:</p>
<blockquote><p>1.使用 compile 函数将正则表达式的字符串形式编译为一个 Pattern 对象<br />2.通过 Pattern 对象提供的一系列方法对文本进行匹配查找,获得匹配结果(一个 Match 对象)<br />3.最后使用 Match 对象提供的属性和方法获得信息,根据需要进行其他的操作里是引用</p></blockquote>
<div class="jb51code"><pre class="brush:py;">re.compile(pattern, flags)</pre></div>
<p><code>compile</code>返回的是一个匹配对象,它单独使用就没有任何意义,需要和findall(), search(), match()搭配使用</p>
<p>5.<code>re.findall</code></p>
<p>在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表<br /><strong>注</strong>: <strong>match 和 search 是匹配一次 findall 匹配所有</strong></p>
<p>6.<code>re.split</code></p>
<div class="jb51code"><pre class="brush:py;">re.split(pattern, string[, maxsplit=0, flags=0])</pre></div>
頁:
[1]