引入標準庫模塊re
match() 和 search():查找到一個匹配后就停止
- match(pattern, string, flags=0):從字符串開頭開始匹配
# 做一次簡單的文本匹配/搜索操作時:
# match():從字符串開頭開始匹配,匹配失敗時返回None
m = re.match('My', 'My name is xuebi')
print(m)
print(m.group()) # 匹配到的內(nèi)容
print(m.start()) # 開始位置
print(m.end()) # 結(jié)束位置
print((m.start(), m.end())) # (開始位置, 結(jié)束位置)
print(m.span()) # (開始位置, 結(jié)束位置)
# m.span() == (m.start(), m.end())
# <re.Match object; span=(0, 2), match='My'>
# My
# 0
# 2
# (0, 2)
# (0, 2)
# 做大量的匹配和搜索操作時:
# 編譯(預(yù)編譯模式):
# 功能上一樣尺锚,執(zhí)行速度更快
p = re.compile('[a-z]+')
m2 = p.match('aaaaMy name is xuebi')
m3 = p.match('xuebi is me')
print(m2)
print(m3)
if p.match('#xuebi is me'):
print('yes')
else:
print('no')
# <re.Match object; span=(0, 4), match='aaaa'>
# <re.Match object; span=(0, 5), match='xuebi'>
# no
- search(pattern, string, flags=0):尋找首次匹配
m = re.search('xuebi', 'kele and xuebi are person? xubi is not.') # 只找第一次出現(xiàn)的
print(m)
# —— <re.Match object; span=(9, 14), match='xuebi'>
findall() 和 finditer():查找字符串中所有的匹配項
# 預(yù)編譯模式
text = 'Today is 2/12/2019. Python starts 23/10/2019. Yesterday is 1-12-2019.'
p = re.compile('\d+[-/]\d+[-/]\d') # [-/]:要么-拼卵,要么/(-或/)
- findall(pattern, string, flags=0):尋找所有匹配項陕习,返回列表
lis = p.findall(text)
print(lis)
# ['2/12/2', '23/10/2', '1-12-2']
- finditer(pattern, string, flags=0):尋找所有匹配項示血,返回迭代器對象
lis = p.finditer(text)
print(lis)
for item in lis:
print(item)
print(item.group())
# <callable_iterator object at 0x030CAC50>
# <re.Match object; span=(9, 15), match='2/12/2'>
# 2/12/2
# <re.Match object; span=(34, 41), match='23/10/2'>
# 23/10/2
# <re.Match object; span=(59, 65), match='1-12-2'>
# 1-12-2
- split(pattern, string, maxsplit=0, flags=0)
msg = 'xuebi@qq.com'
lis = msg.split('@')
print(lis)
# —— ['xuebi', 'qq.com']
line = 'asdf fjdk; afed, fjek,asdf, foo'
lis1 = re.split(r'[,;\s]+', line) # 按逗號或分號或空白字符中一次或多次進行分割
lis2 = re.split(r'[,;\s]\s*', line) # 按逗號或分號或空白字符且他們的后面再接0個或多個空白字符進行分割
print(lis1) # 按原生字符串分割氧卧,\s匹配任意一個空白字符包括[ \t\n\r\f\v]
print(lis2)
# —— ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
# —— ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
str.replace() 和 sub() 和 subn():
# 對于簡單的替換,可以用str.replace()方法
text = 'yeah, but no, but yeah, but no, but yeah'
text = text.replace('yeah', 'yes')
print(text)
# —— yes, but no, but yes, but no, but yes
- sub(pattern, repl, string, count=0, flags=0)
# 對于復(fù)雜的替換蚜锨,可以用正則表達式中的sub()方法
# sub()替換匹配
p = re.compile(r'(\d+)/(\d+)/(\d+)')
text = 'Today is 12/2/2019. PyCon starts 10/23/2019.'
text = p.sub(r'\3-\1-\2', text) # \3\2\1為group()對應(yīng)的組元素
print(text)
# —— Today is 2019-12-2. PyCon starts 2019-10-23.
# 對于更復(fù)雜的替換,可以傳遞一個替換回調(diào)函數(shù)來代替慢蜓。
# 一個替換回調(diào)函數(shù)的參數(shù)是一個Match對象亚再,也就是match()或者find()返回的對象。
# 使用group()方法來提取特定的匹配部分晨抡。
# 回調(diào)函數(shù)最后返回替換字符串氛悬。
from calendar import month_abbr
def change_date(m):
mon_name = month_abbr[int(m.group(1))]
return '{} {} {}'.format(m.group(2), mon_name, m.group(3))
text = 'Today is 12/2/2019. PyCon starts 10/23/2019.'
text = p.sub(change_date, text)
print(text)
# —— Today is 2 Dec 2019. PyCon starts 23 Oct 2019.
- subn(pattern, repl, string, count=0, flags=0)
# subn():可查出替換了多少次
newtext, n = p.subn(change_date, text)
print(newtext)
print(n)
# Today is 2 Dec 2019. PyCon starts 23 Oct 2019.
# 0
類似的還有:
fullmatch(pattern, string, flags=0)
compile(pattern, flags=0)
purge()
template(pattern, flags=0)
......
【拓展】回調(diào)函數(shù)
解決模塊之間不能循環(huán)調(diào)用的問題
=================================
普通字符集
# 普通字符:普通的文本值代表自身,用于匹配非特殊字符
print(re.search('My', 'My name is xuebi')) # My匹配My
# —— <re.Match object; span=(0, 2), match='My'>
# .:可匹配換行符\n以外的任意一個字符耘柱。
print(re.search('.', 'My name is xuebi')) # 匹配一個非換行符
# —— <re.Match object; span=(0, 1), match='M'>
print(re.search('ab.', 'abCMy name is xuebi')) # 匹配ab和一個非換行符
print(re.search('...', 'ab CMy name is xuebi')) # 匹配三個非換行符
print(re.search('ab.', 'ab')) # 匹配ab和一個非換行符
# —— <re.Match object; span=(0, 3), match='ab '>
# —— <re.Match object; span=(0, 3), match='ab '>
# —— None
# \:轉(zhuǎn)義字符
print(re.search('xuebi.', 'xuebi.com')) # 匹配xuebi和一個非換行字符
print(re.search('xuebi\.', 'xuebi.com')) # 匹配xuebi和一個.字符
print(re.search('xuebi\.', 'xuebicom')) # 匹配xuebi和一個.字符
# —— <re.Match object; span=(0, 6), match='xuebi.'>
# —— <re.Match object; span=(0, 6), match='xuebi.'>
# —— None
# []:匹配中括號內(nèi)的一個字符(括號里內(nèi)容不限)
# 1. 中括號內(nèi)的字符可以全部列出如捅,如[abc]表示匹配字符a或b或c
# 2. 也可以使用-表示范圍,如[a-z]表示匹配所以小寫字母中的任意一個字符
# 3. 本文后續(xù)要介紹的如*调煎、+等特殊字符在中括號內(nèi)將失去特殊含義镜遣,如[*+()]表示匹配字符*或+或(或)
# 4. 本文后續(xù)要介紹的特殊字符集如\d、\w等也可以放入此中括號內(nèi)士袄,繼續(xù)保持特殊含義
# 5. 如果中括號內(nèi)的字符序列前面有一個^悲关,表示不匹配中括號內(nèi)的任何一個字符谎僻,如[^0-9]表示不匹配數(shù)字,a[^0-9]c不匹配a1c寓辱,但會匹配abc
# 6. 要匹配字符]艘绍,可以轉(zhuǎn)義它,或者把它放在中括號內(nèi)的首位秫筏,如a[()[\]{}]c或a[]()[{}]c都可以匹配到a]c
print(re.search('[abc]', 'a_xuebicom')) # 匹配a或b或c
print(re.search('[a-z]', 'a_xuebicom')) # 匹配a到z中任意一個
print(re.search('[*+()]', '(_xuebicom)')) # 匹配字符 * 或 + 或 ( 或 )
print()
print(re.search('[^*+()]', '(_xuebicom)')) # 匹配非字符 * 或 + 或 ( 或 )
print(re.search('[a[()[\]{}]]c', '(a]c_xuebicom)')) # 匹配a或]或(或)或[或{或} 和 ]和c
# 等價于下一句
print(re.search('a[]()[{}]c', '(a]c_xuebicom)')) # 匹配a 和]或(或)或[或{或} 和 c
# <re.Match object; span=(0, 1), match='a'>
# <re.Match object; span=(0, 1), match='a'>
# <re.Match object; span=(0, 1), match='('>
# 特殊字符集如\d诱鞠、\w等例子請往下看
# <re.Match object; span=(1, 2), match='_'>
# <re.Match object; span=(1, 4), match='a]c'>
# <re.Match object; span=(1, 4), match='a]c'>
特殊字符集
# \d:匹配任意一個數(shù)字字符,等價于[0-9]
# \D:匹配任意一個非數(shù)字字符这敬,等價于[^0-9]
# \s:匹配任意一個空白字符般甲,等價于[ \t\n\r\f\v]
# \S:匹配任意一個非空字符,等價于[^ \t\n\r\f\v]
# \w:匹配任意一個alphanumeric character鹅颊,等價于[a-zA-Z0-9_]
# \W:匹配任意一個non-alphanumeric character敷存,等價于[^a-zA-Z0-9_]
print(re.search('a\db', 'xba1b)')) # 匹配a和一個數(shù)字字符和b
# a\db == a[0-9]b
print(re.search('a\Db', 'xbaAb)')) # 匹配a和一個非數(shù)字字符和b
# a\Db == a[^0-9]b
print(re.search('a\sb', 'xba b)')) # 匹配a和一個空白字符和b
# a\sb == a[ \t\n\r\f\v]b
print(re.search('a\Sb', 'xbaCb)')) # 匹配a和一個非空白字符和b
# a\Sb == a[^ \t\n\r\f\v]b
print(re.search('a\wb', 'xba_b)')) # 匹配a和一個alphanumeric character和b
# a\wb == a[a-zA-Z0-9_]b
print(re.search('a\Wb', 'xba b)')) # 匹配a和一個non-alphanumeric character和b
# a\Wb == a[^a-zA-Z0-9_]b
# <re.Match object; span=(2, 5), match='a1b'>
# <re.Match object; span=(2, 5), match='aAb'>
# <re.Match object; span=(2, 5), match='a b'>
# <re.Match object; span=(2, 5), match='aCb'>
# <re.Match object; span=(2, 5), match='a_b'>
# <re.Match object; span=(2, 5), match='a b'>
# 【例子】
import string
printable = string.printable
print(re.findall('\d', printable))
# ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
print(re.findall('\w', printable), end='')
# ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
# 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
# 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
# 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
# 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
# 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
# 'Y', 'Z', '_']
print(re.findall('\s', printable))
# [' ', '\t', '\n', '\r', '\x0b', '\x0c']
print(re.findall('\w', 'abc' + '-/*' + '\u00ea' + '\u0115'))
# ['a', 'b', 'c', 'ê', '?']
數(shù)量
# prev* :匹配0個或多個prev,盡可能多地匹配堪伍,貪婪模式
# prev*? :匹配0個或多個prev锚烦,盡可能少地匹配,非貪婪模式
# prev+ :匹配1個或多個prev帝雇,盡可能多地匹配涮俄,貪婪模式
# prev+? :匹配1個或多個prev,盡可能少地匹配尸闸,非貪婪模式
# prev? :匹配0個或多個prev彻亲,盡可能多地匹配,貪婪模式
# prev?? :匹配0個或多個prev吮廉,盡可能少地匹配苞尝,非貪婪模式
# prev{m} :匹配m個連續(xù)的prev
# prev{m,n} :匹配m個到n個連續(xù)的prev,盡可能多地匹配宦芦,貪婪模式
# prev{m,n}? :匹配m個到n個連續(xù)的prev宙址,盡可能少地匹配,非貪婪模式
print(re.findall('ab*', 'ab'))
print(re.findall('ab*', 'a_ab_abbb'))
# ['ab']
# ['a', 'ab', 'abbb']
print(re.findall('ab*?', 'ab'))
print(re.findall('ab*?', 'a_ab_abbb'))
# ['a']
# ['a', 'a', 'a']
print(re.findall('ab+', 'abb'))
print(re.findall('ab+', 'a_ab_abbb'))
# ['abb']
# ['ab', 'abbb']
print(re.findall('ab+?', 'abb'))
print(re.findall('ab+?', 'a_ab_abbb'))
# ['ab']
# ['ab', 'ab']
print(re.findall('ab?', 'abb'))
print(re.findall('ab?', 'a_ab_abbb'))
# ['ab']
# ['a', 'ab', 'ab']
print(re.findall('ab??', 'abb'))
print(re.findall('ab??', 'a_ab_abbb'))
# ['a']
# ['a', 'a', 'a']
print(re.findall('a{3}', 'aaaa'))
print(re.findall('a{3}', 'a_aa_aaa'))
# ['aaa']
# ['aaa']
print(re.findall('a{1,3}', 'aaaaa'))
print(re.findall('a{1,3}', 'aaaaaaa'))
print(re.findall('a{1,3}', 'a_aa_aaa'))
# ['aaa', 'aa']
# ['aaa', 'aaa', 'a']
# ['a', 'aa', 'aaa']
print(re.findall('a{1,3}?', 'aa'))
print(re.findall('a{1,3}?', 'a_aa_aaa'))
# ['a', 'a']
# ['a', 'a', 'a', 'a', 'a', 'a']
# 可以在*或+或?的后面再添加一個?调卑,此時表示非貪婪模式匹配抡砂,Python中的正則表達式默認是貪婪模式匹配,它會在滿足整個表達式要求的前提下恬涧,盡可能多地去匹配字符
邊界
# ^prev:匹配以prev開頭的字符串
# prev$:匹配以prev結(jié)尾的字符串
# \b:單詞邊界注益。\b在Python中默認會被轉(zhuǎn)義為\x08表示退格,需要將整個正則表達式指定為原始字符串(在前面加個r)
# \B:非單詞邊界
# \Aprev:匹配以prev開頭的字符串
# prev\Z:匹配以prev結(jié)尾的字符串
print(re.findall('^ab_', 'ab_cd'))
print(re.findall('^.*_ab', '1+x_ab_cd_ab'))
# ['ab_']
# ['1+x_ab_cd_ab']
print(re.findall('_ab$', 'ab_cd_ab'))
print(re.findall('.*_ab$', '1+x_ab_cd_ab'))
# ['_ab']
# ['1+x_ab_cd_ab']
print(re.findall(r'\bfoo\b', ' foo foo.(foo)'))
print(re.findall(r'\bfoo\b', ' foobar _foo1'))
# ['foo', 'foo', 'foo']
# []
print(re.findall(r'py\B', 'pythonpy3py2'))
print(re.findall(r'py\B', 'py py.py!'))
# ['py', 'py', 'py']
# []
print(re.findall(r'\Aab', 'abcde'))
print(re.findall(r'\Aab', '_abcde'))
# ['ab']
print(re.findall(r'ab\Z', '123ab'))
print(re.findall(r'ab\Z', '123ab_'))
# ['ab']
# []
# 【例】
import re
s = 'I wish I may, I wish I might have a dish of fish tonight.'
m = re.search(r'(. dish\b).*(\bfish)', s)
print(m.group())
print(m.groups())
print(m.group(0))
print(m.group(1))
print(m.group(2))
# a dish of fish
# ('a dish', 'fish')
# a dish of fish
# a dish
# fish
分組
# (expr):將小括號內(nèi)的表達式作為一個分組溯捆,后面可以接表示數(shù)量的特殊字符
# expr1|expr2:匹配expr1或expr2丑搔,等價于[expr1expr2]
# \1:引用編號為1的分組匹配到的字符串。類似的還有\(zhòng)0\2\3...
# (?P<NAME>expr):類似于(expr),同時給分組制定了一個別名NAME低匙,注意時大寫的字母P
# (?P=NAME):引用別名為NAME的分組旷痕,當然也可以繼續(xù)使用編號形式引用分組,此時要加r制定為原始字符串顽冶。
print(re.findall('a(bc)?d', 'abcdd'))
print(re.findall('a(bc)?d', 'abcbcd'))
# ['bc']
# []
print(re.findall('p(i|u)g', 'pug_pig'))
# ['u', 'i']
print(re.findall(r'a(\d)b\1c\1d', 'a3b3c3d'))
# ['3']
print(re.findall(r'a(?P<quote>\d)b\1c(?P=quote)d', 'a3b3c3d'))
# ['3']
# 【例】
m2 = re.search(r'(?P<DISH>. dish\b).*(?P<FISH>\bfish)', s)
print(m2.groups())
print(m2.group())
print(m2.group('DISH'))
print(m2.group('FISH'))
print(m2.group(1))
print(m2.group(2))
# ('a dish', 'fish')
# a dish of fish
# a dish
# fish
# a dish
# fish
拓展語法
# (?:expr):非捕獲組(成為整體但不成組)
# prev(?=next):環(huán)視欺抗,如果后面為next,則返回prev
# prev(?!next):環(huán)視强重,如果后面不是next绞呈,則返回prev
# (?<=prev)next:環(huán)視,如果前面為prev间景,則返回next
# (?<!\d)next:環(huán)視佃声,如果前面不是prev,則返回next
print(re.findall('a(?:\d)+bc', 'a333bc'))
# print(re.findall(r'a(?:\d)+b\1c', 'a333bc')) # 語法錯誤
# ['a333bc']
print(re.findall('ab(?=\d)', 'ab3_+')) # ab后緊跟一個數(shù)字時倘要,輸出ab
# ['ab']
print(re.findall('ab(?!\d)', 'abc_+')) # ab后緊跟一個非數(shù)字時圾亏,輸出ab
# ['ab']
print(re.findall('(?<=\d)ab', '_+1ab')) # ab前緊跟一個數(shù)字時,輸出ab
# ['ab']
print(re.findall('(?<!\d)ab', '_+ab')) # ab前緊跟一個非數(shù)字時封拧,輸出ab
# ['ab']
# 【例】
import re
line = 'asdf fjdk; afed, fjek,asdf, foo'
print(re.split(r'[;,\s]\s*', line)) # 使用多個分割符或者是分隔符周圍不確定的空格時志鹃,來分割一個字符串
print(re.split(r'(;|,|\s)\s*', line)) # 使用括號時被匹配的文本(那些分隔符)也將出現(xiàn)在結(jié)果列表中
print(re.split(r'(?:,|;|\s)\s*', line)) # 不想保留分割字符串到結(jié)果列表中去,但仍然需要使用到括號來分組正則表達式的話泽西, 確保你的分組是非捕獲分組曹铃,形如(?:...)
# ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
# ['asdf', ' ', 'fjdk', ';', 'afed', ',', 'fjek', ',', 'asdf', ',', 'foo']
# ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
實例1 — — 字符串忽略大小寫的搜索替換
# 【實例1-1】為了在文本操作時忽略大小寫,你需要在使用re模塊的時候給這些操作提供re.IGNORECASE標志參數(shù)
import re
text = 'UPPER PYTHON, lower python, Mixed Python'
print(re.findall('python', text))
print(re.findall('python', text, flags=re.IGNORECASE))
print(re.sub('python', 'snake', text, flags=re.IGNORECASE))
# ['python']
# ['PYTHON', 'python', 'Python']
# UPPER snake, lower snake, Mixed snake
# 弊端:這樣不管原字符串中的是大寫捧杉、小寫或首字母大寫的python陕见,全替換為小寫的snake
# 【實例1-2】替換字符串能自動跟被匹配字符串的大小寫保持一致
import re
text = 'UPPER PYTHON, lower python, Mixed Python'
def matchcase(word):
def replace(m):
text = m.group()
if text.isupper():
return word.upper()
elif text.islower():
return word.lower()
elif text[0].isupper():
return word.capitalize()
else:
return word
return replace
print(re.sub('python', matchcase('snake'), text, flags=re.IGNORECASE))
# UPPER SNAKE, lower snake, Mixed Snake
# matchcase('snake')返回了一個回調(diào)函數(shù)
# 【拓展】Python支持的其它正則表達式的標志位flags:
# re.A: 或re.ASCII,使\w/\W/d/\D/\s/\S/\b/\B只匹配ASCII字符味抖,不匹配Unicode字符评甜。
# re.I: 或re.IGNORECASE,忽略大小寫非竿,[A-Z]會匹配小寫字母蜕着。
# re.M: 或re.MULTILINE,多行模式红柱,改變^或$的默認行為。
# re.S: 或re.DOTALL蓖乘,Make the.special character match any character at all, including a newline; without this flag, .will match anything except a newline锤悄。
# re.U: 或re.UNICODE,默認使用此標志位嘉抒,\w/\W/d/\D/\s/\S/\b/\B會匹配Unicode字符零聚,如果指定了re.A標志,則re.U失效。
# re.X: 或re.VERBOSE隶症,允許整個正則表達式寫成多行政模,忽略空白字符,并可以添加#開頭的注釋蚂会,這樣更美觀淋样。
# 【實例】
import re
a = re.compile(r"""\d + # the integral part
\. # the decimal point
\d * # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")
print(a.match('10.2'))
print(b.match('10.2'))
# <re.Match object; span=(0, 4), match='10.2'>
# <re.Match object; span=(0, 4), match='10.2'>
# 【實例】一次指定多個標志位
import re
text = '''UPPER PYTHON
lower python
Mixed Python'''
print(re.sub('python$', 'snake', text))
# UPPER PYTHON
# lower python
# Mixed Python
print(re.sub('python$', 'snake', text, flags=re.IGNORECASE))
# UPPER PYTHON
# lower python
# Mixed snake
print(re.sub('python$', 'snake', text, flags=re.IGNORECASE|re.MULTILINE))
# UPPER snake
# lower snake
# Mixed snake
p = re.compile(r'python$', re.I|re.M)
print(p)
# re.compile('python$', re.IGNORECASE|re.MULTILINE)
print(p.sub('snake', text))
# UPPER snake
# lower snake
# Mixed snake
print(re.sub('(?im)python$', 'snake', text))
# UPPER snake
# lower snake
# Mixed snake
實例2 — — 最短匹配模式: 非貪婪
# 【實例2-1】試著用正則表達式匹配某個文本模式丘侠,但是它找到的是模式的最長可能匹配
import re
p = re.compile(r'"(.*)"')
text1 = 'Computer says "no."'
print(p.findall(text1))
text2 = 'Computer says "no." Phone says "yes."'
print(p.findall(text2)) # 默認是貪婪模式囤屹,(.*)會盡可能多的匹配博肋,只要后面有一個"就能滿足整個正則检号,所以匹配到最后一個冒號之前了
# ['no.']
# ['no." Phone says "yes.']
# 【實例2-2】修正2-1的問題在模式中的*操作符后面加上?修飾符
p2 = re.compile(r'"(.*?)"')
print(p2.findall(text2))
# ['no.', 'yes.']
實例3 — — 多行匹配
# 試著使用正則表達式去匹配一大塊的文本断医,而你需要跨越多行去匹配萌腿,當你用點.去匹配任意字符的時候嘉竟,忘記了點.不能匹配換行符\n的事實渐尿。
# 【實例3-1】試著去匹配C語言分割的注釋
import re
text1 = '/* this is a comment */'
text2 = '''/* this is a
multiline comment */
'''
p = re.compile(r'/\*(.*?)\*/')
print(p.findall(text1)) # 能正確匹配單行
print(p.findall(text2)) # . 點號不能匹配多行中的換行符余指,所以整體匹配失敗
# [' this is a comment ']
# []
# 【實例3-2】改進3-1捕犬,可以使用.|\n匹配所有字符,或者指定re.DOTALL標志位
p2 = re.compile(r'/\*((?:.|\n)*?)\*/')
print(p2.findall(text2))
p3 = re.compile(r'/\*(.*?)\*/', re.DOTALL)
print(p3)
print(p3.findall(text2))
# [' this is a\nmultiline comment ']
# re.compile('/\\*(.*?)\\*/', re.DOTALL)
# [' this is a\nmultiline comment ']
# 【例3-3】re.MULTILINE多行模式的用法
import re
text = 'This is some text -- with punctuation.\nA second line.'
pattern = r'(^\w+)|(\w+\S*$)'
single_line = re.compile(pattern)
multiline = re.compile(pattern, re.MULTILINE)
print('Single Line :')
for match in single_line.findall(text):
print(' {!r}'.format(match))
print('Multline :')
for match in multiline.findall(text):
print(' {!r}'.format(match))
# Single Line :
# ('This', '')
# ('', 'line.')
# Multline :
# ('This', '')
# ('', 'punctuation.')
# ('A', '')
# ('', 'line.')