字符串与文本03-非贪婪模式 / 多行匹配模式 / Unicode文本标准化

非贪婪模式

  • 使用 “ ?”
import re

#定义正则,匹配引号内的内容
rul = re.compile(r'\"(.*)\"')

#完美匹配
text1 = '贫僧法号 "不懂"'
print(rul.findall(text1))   #['不懂']

#不完整匹配
text2 = '贫僧法号 "不懂" .贫道法号 "不问"'
print(rul.findall(text2))   #['不懂" .贫道法号 "不问']

在正则表达式中 * 操作符是贪婪的,因此匹配操作会查找最长的可能匹配。于是在第二个
例子中搜索 text2 的时候返回结果并不是我们想要的。此时需要使用非贪婪模式:“?”

#定义非贪婪的正则
str_pat = re.compile(r'\"(.*?)\"')
print(str_pat.findall(text2))    #['不懂', '不问']

多行匹配模式

  • 使用 (?:.|\n)
import re

#定义正则
rul = re.compile(r'/\*(.*?)\*/')

text1 = '/* 这是一句话 */'
text2 = '''
    /* 这是一句话,
    但是还有第二句,
    另外还有第三句   */
'''
#完美匹配
print(rul.findall(text1))   # [' 这是一句话 ']
#不完美匹配
print(rul.findall(text2))   # []

当你用点 (.) 去匹配任意字符的时候,忘记了点 (.) 不能匹配换行符的事实。匹配不到多行内容。这时需修改模式字符串,增加对换行的支持

#正则添加(?:.|\n)
rul2 = re.compile(r'/\*((?:.|\n)*?)\*/')
#完美匹配
print(rul2.findall(text2))   #['这是一句话,\n 但是还有第二句,\n 另外还有第三句']


  • 使用标志参数 re.DOTALL

re.compile() 函数接受一个标志参数叫 re.DOTALL ,它也可以让正则表达式中的点 (.) 匹配包括换行符在内的任意字符。
#使用re.compile()
rul3 = re.compile(r'/\*(.*?)\*/', re.DOTALL)
#完美匹配
print(rul3.findall(text2))   #[' 这是一句话,\n 但是还有第二句,\n 另外还有第三句   ']

将 Unicode 文本标准化

#这里有两个文本
s1 = 'Spicy Jalape\u00f1o'
s2 = 'Spicy Jalapen\u0303o'

print(s1)         #'Spicy Jalapeño'
print(s2)         #'Spicy Jalapeño'
print(s1 == s2)   #False
print(len(s1))    #14
print(len(s2))    #15

”’打印出来虽然相同,但却是两个不同形式的东西,第一种使用整体字符”ñ”(U+00F1),第二种使用拉丁字母”n” 后面跟一个”˜” 的组合字符 (U+0303)。”’
在需要比较字符串的程序中使用字符的多种表示往往会产生问题。

  • 以使用 unicodedata.normalize()
import unicodedata

#使用整体组成的标准化方式NFC
t1 = unicodedata.normalize('NFC', s1)
t2 = unicodedata.normalize('NFC', s2)
print(t1 == t2)      #True
print(ascii(t1))     #'Spicy Jalape\xf1o'

#使用多组合的标准化方式NFD
t3 = unicodedata.normalize('NFD', s1)
t4 = unicodedata.normalize('NFD', s2)
print(t3 == t4)     #True
print(ascii(t3))    #'Spicy Jalapen\u0303o'>

normalize() 第一个参数指定字符串标准化的方式。NFC 表示字符应该是整体组
成 (比如可能的话就使用单一编码),而 NFD 表示字符应该分解为多个组合字符表示

猜你喜欢

转载自blog.csdn.net/xiangchi7/article/details/82380125