python正则表达式处理txt_Python文本处理服务(re正则表达式例子)
正則表達式例子
檢查對子
在此示例中,我們將使用以下幫助函數來更優雅地顯示匹配對象:
def?displaymatch(match):????if?match?is?None:????????return?None????return?''?%?(match.group(),?match.groups())
假設你在寫一個撲克程序,一個玩家的一手牌為五個字符的串,每個字符表示一張牌,"a" 就是 A, "k" K, "q" Q, "j" J, "t" 為 10, "2" 到 "9" 表示2 到 9。
要看給定的字符串是否有效,我們可以按照以下步驟
>>>>>>?valid?=?re.compile(r"^[a2-9tjqk]{5}$")>>>?displaymatch(valid.match("akt5q"))??#?Valid."">>>?displaymatch(valid.match("akt5e"))??#?Invalid.>>>?displaymatch(valid.match("akt"))????#?Invalid.>>>?displaymatch(valid.match("727ak"))??#?Valid.""
最后一手牌,"727ak" ,包含了一個對子,或者兩張同樣數值的牌。要用正則表達式匹配它,應該使用向后引用如下
>>>>>>?pair?=?re.compile(r".*(.).*\1")>>>?displaymatch(pair.match("717ak"))?????#?Pair?of?7s."">>>?displaymatch(pair.match("718ak"))?????#?No?pairs.>>>?displaymatch(pair.match("354aa"))?????#?Pair?of?aces.""
要找出這對組成的卡,可以按以下方式使用match對象的group()方法:
>>>pair.match("717ak").group(1)'7'# Error because re.match() returns None, which doesn't have a group() method:>>>pair.match("718ak").group(1)Traceback (most recent call last):File "", line 1, in re.match(r".*(.).*\1", "718ak").group(1)AttributeError: 'NoneType' object has no attribute 'group'>>>pair.match("354aa").group(1)'a'
模擬 scanf()
Python 目前沒有一個類似c函數 scanf() 的替代品。正則表達式通常比 scanf() 格式字符串要更強大一些,但也帶來更多復雜性。下面的表格提供了 scanf() 格式符和正則表達式大致相同的映射。
scanf()?格式符正則表達式%c.
%5c.{5}
%d[-+]?\d+
%e,?%E,?%f,?%g[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?
%i[-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)
%o[-+]?[0-7]+
%s\S+
%u\d+
%x,?%X[-+]?(0[xX])?[\dA-Fa-f]+
從文件名和數字提取字符串
/usr/sbin/sendmail?-?0?errors,?4?warnings
你可以使用 scanf() 格式化
%s?-?%d?errors,?%d?warnings
等價的正則表達式是:
(\S+)?-?(\d+)?errors,?(\d+)?warnings
search() vs. match()
Python 提供了兩種不同的操作:基于 re.match() 檢查字符串開頭,或者 re.search() 檢查字符串的任意位置(默認Perl中的行為)。
例如
>>>>>>?re.match("c",?"abcdef")????#?No?match>>>?re.search("c",?"abcdef")???#?Match
在 search() 中,可以用 '^' 作為開始來限制匹配到字符串的首位
>>>>>>?re.match("c",?"abcdef")????#?No?match>>>?re.search("^c",?"abcdef")??#?No?match>>>?re.search("^a",?"abcdef")??#?Match
注意 MULTILINE 多行模式中函數 match() 只匹配字符串的開始,但使用 search() 和以 '^' 開始的正則表達式會匹配每行的開始
>>>>>>?re.match('X',?'A\nB\nX',?re.MULTILINE)??#?No?match>>>?re.search('^X',?'A\nB\nX',?re.MULTILINE)??#?Match
建立一個電話本
split() 將字符串用參數傳遞的樣式分隔開。這個方法對于轉換文本數據到易讀而且容易修改的數據結構,是很有用的,如下面的例子證明。
首先,這是輸入。通常它可能來自文件,這里我們使用三引號字符串語法:
>>>>>>?text?=?"""Ross?McFluff:?834.345.1254?155?Elm?Street......?Ronald?Heathmore:?892.345.3428?436?Finley?Avenue...?Frank?Burger:?925.541.7625?662?South?Dogwood?Way.........?Heather?Albrecht:?548.326.4584?919?Park?Place"""
條目用一個或者多個換行符分開。現在我們將字符串轉換為一個列表,每個非空行都有一個條目:
>>>?entries?=?re.split("\n+",?text)>>>?entries['Ross?McFluff:?834.345.1254?155?Elm?Street','Ronald?Heathmore:?892.345.3428?436?Finley?Avenue','Frank?Burger:?925.541.7625?662?South?Dogwood?Way','Heather?Albrecht:?548.326.4584?919?Park?Place']
最終,將每個條目分割為一個由名字、姓氏、電話號碼和地址組成的列表。我們為 split() 使用了 maxsplit 形參,因為地址中包含有被我們作為分割模式的空格符:
>>>?[re.split(":??",?entry,?3)?for?entry?in?entries][['Ross',?'McFluff',?'834.345.1254',?'155?Elm?Street'],['Ronald',?'Heathmore',?'892.345.3428',?'436?Finley?Avenue'],['Frank',?'Burger',?'925.541.7625',?'662?South?Dogwood?Way'],['Heather',?'Albrecht',?'548.326.4584',?'919?Park?Place']]
:? 樣式匹配姓后面的冒號,因此它不出現在結果列表中。如果 maxsplit 設置為 4 ,我們還可以從地址中獲取到房間號:
>>>?[re.split(":??",?entry,?4)?for?entry?in?entries][['Ross',?'McFluff',?'834.345.1254',?'155',?'Elm?Street'],['Ronald',?'Heathmore',?'892.345.3428',?'436',?'Finley?Avenue'],['Frank',?'Burger',?'925.541.7625',?'662',?'South?Dogwood?Way'],['Heather',?'Albrecht',?'548.326.4584',?'919',?'Park?Place']]
文字整理
sub() 替換字符串中出現的樣式的每一個實例。這個例子證明了使用 sub() 來整理文字,或者隨機化每個字符的位置,除了首位和末尾字符
>>>>>>?def?repl(m):...?????inner_word?=?list(m.group(2))...?????random.shuffle(inner_word)...?????return?m.group(1)?+?"".join(inner_word)?+?m.group(3)>>>?text?=?"Professor?Abdolmalek,?please?report?your?absences?promptly.">>>?re.sub(r"(\w)(\w+)(\w)",?repl,?text)'Poefsrosr?Aealmlobdk,?pslaee?reorpt?your?abnseces?plmrptoy.'>>>?re.sub(r"(\w)(\w+)(\w)",?repl,?text)'Pofsroser?Aodlambelk,?plasee?reoprt?yuor?asnebces?potlmrpy.'
找到所有副詞
findall() 匹配樣式 所有 的出現,不僅是像 search() 中的第一個匹配。比如,如果一個作者希望找到文字中的所有副詞,他可能會按照以下方法用 findall()
>>>>>>?text?=?"He?was?carefully?disguised?but?captured?quickly?by?police.">>>?re.findall(r"\w+ly",?text)['carefully',?'quickly']
找到所有副詞和位置
如果需要匹配樣式的更多信息, finditer() 可以起到作用,它提供了 匹配對象 作為返回值,而不是字符串。繼續上面的例子,如果一個作者希望找到所有副詞和它的位置,可以按照下面方法使用 finditer()
>>>>>>?text?=?"He?was?carefully?disguised?but?captured?quickly?by?police.">>>?for?m?in?re.finditer(r"\w+ly",?text):...?????print('%02d-%02d:?%s'?%?(m.start(),?m.end(),?m.group(0)))07-16:?carefully40-47:?quickly
原始字符記法
原始字符串記法 (r"text") 保持正則表達式正常。否則,每個正則式里的反斜杠('\') 都必須前綴一個反斜杠來轉義。比如,下面兩行代碼功能就是完全一致的
>>>>>>?re.match(r"\W(.)\1\W",?"?ff?")>>>?re.match("\\W(.)\\1\\W",?"?ff?")
當需要匹配一個字符反斜杠,它必須在正則表達式中轉義。在原始字符串記法,就是 r"\\"。否則就必須用 "\\\\",來表示同樣的意思
>>>>>>?re.match(r"\\",?r"\\")>>>?re.match("\\\\",?r"\\")
寫一個詞法分析器
一個 詞法器或詞法分析器 分析字符串,并分類成目錄組。這是寫一個編譯器或解釋器的第一步。
文字目錄是由正則表達式指定的。這個技術是通過將這些樣式合并為一個主正則式,并且循環匹配來實現的
import collectionsimport reToken = collections.namedtuple('Token', ['type', 'value', 'line', 'column'])def tokenize(code):keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}token_specification = [('NUMBER', ? r'\d+(\.\d*)?'), ?# Integer or decimal number('ASSIGN', ? r':='), ? ? ? ? ? # Assignment operator('END', ? ? ?r';'), ? ? ? ? ? ?# Statement terminator('ID', ? ? ? r'[A-Za-z]+'), ? ?# Identifiers('OP', ? ? ? r'[+\-*/]'), ? ? ?# Arithmetic operators('NEWLINE', ?r'\n'), ? ? ? ? ? # Line endings('SKIP', ? ? r'[ \t]+'), ? ? ? # Skip over spaces and tabs('MISMATCH', r'.'), ? ? ? ? ? ?# Any other character]tok_regex = '|'.join('(?P%s)' % pair for pair in token_specification)line_num = 1line_start = 0for mo in re.finditer(tok_regex, code):kind = mo.lastgroupvalue = mo.group()column = mo.start() - line_startif kind == 'NUMBER':value = float(value) if '.' in value else int(value)elif kind == 'ID' and value in keywords:kind = valueelif kind == 'NEWLINE':line_start = mo.end()line_num += 1continueelif kind == 'SKIP':continueelif kind == 'MISMATCH':raise RuntimeError(f'{value!r} unexpected on line {line_num}')yield Token(kind, value, line_num, column)statements = '''IF quantity THENtotal := total + price * quantity;tax := price * 0.05;ENDIF;'''for token in tokenize(statements):print(token)
這個詞法器產生以下輸出
Token(type='IF',?value='IF',?line=2,?column=4)Token(type='ID',?value='quantity',?line=2,?column=7)Token(type='THEN',?value='THEN',?line=2,?column=16)Token(type='ID',?value='total',?line=3,?column=8)Token(type='ASSIGN',?value=':=',?line=3,?column=14)Token(type='ID',?value='total',?line=3,?column=17)Token(type='OP',?value='+',?line=3,?column=23)Token(type='ID',?value='price',?line=3,?column=25)Token(type='OP',?value='*',?line=3,?column=31)Token(type='ID',?value='quantity',?line=3,?column=33)Token(type='END',?value=';',?line=3,?column=41)Token(type='ID',?value='tax',?line=4,?column=8)Token(type='ASSIGN',?value=':=',?line=4,?column=12)Token(type='ID',?value='price',?line=4,?column=15)Token(type='OP',?value='*',?line=4,?column=21)Token(type='NUMBER',?value=0.05,?line=4,?column=23)Token(type='END',?value=';',?line=4,?column=27)Token(type='ENDIF',?value='ENDIF',?line=5,?column=4)Token(type='END',?value=';',?line=5,?column=9)
正則表達式例子
檢查對子
在此示例中,我們將使用以下幫助函數來更優雅地顯示匹配對象:
def?displaymatch(match):????if?match?is?None:????????return?None????return?''?%?(match.group(),?match.groups())
假設你在寫一個撲克程序,一個玩家的一手牌為五個字符的串,每個字符表示一張牌,"a" 就是 A, "k" K, "q" Q, "j" J, "t" 為 10, "2" 到 "9" 表示2 到 9。
要看給定的字符串是否有效,我們可以按照以下步驟
>>>>>>?valid?=?re.compile(r"^[a2-9tjqk]{5}$")>>>?displaymatch(valid.match("akt5q"))??#?Valid."">>>?displaymatch(valid.match("akt5e"))??#?Invalid.>>>?displaymatch(valid.match("akt"))????#?Invalid.>>>?displaymatch(valid.match("727ak"))??#?Valid.""
最后一手牌,"727ak" ,包含了一個對子,或者兩張同樣數值的牌。要用正則表達式匹配它,應該使用向后引用如下
>>>>>>?pair?=?re.compile(r".*(.).*\1")>>>?displaymatch(pair.match("717ak"))?????#?Pair?of?7s."">>>?displaymatch(pair.match("718ak"))?????#?No?pairs.>>>?displaymatch(pair.match("354aa"))?????#?Pair?of?aces.""
要找出這對組成的卡,可以按以下方式使用match對象的group()方法:
>>>pair.match("717ak").group(1)'7'# Error because re.match() returns None, which doesn't have a group() method:>>>pair.match("718ak").group(1)Traceback (most recent call last):File "", line 1, in re.match(r".*(.).*\1", "718ak").group(1)AttributeError: 'NoneType' object has no attribute 'group'>>>pair.match("354aa").group(1)'a'
模擬 scanf()
Python 目前沒有一個類似c函數 scanf() 的替代品。正則表達式通常比 scanf() 格式字符串要更強大一些,但也帶來更多復雜性。下面的表格提供了 scanf() 格式符和正則表達式大致相同的映射。
scanf()?格式符正則表達式%c.
%5c.{5}
%d[-+]?\d+
%e,?%E,?%f,?%g[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?
%i[-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)
%o[-+]?[0-7]+
%s\S+
%u\d+
%x,?%X[-+]?(0[xX])?[\dA-Fa-f]+
從文件名和數字提取字符串
/usr/sbin/sendmail?-?0?errors,?4?warnings
你可以使用 scanf() 格式化
%s?-?%d?errors,?%d?warnings
等價的正則表達式是:
(\S+)?-?(\d+)?errors,?(\d+)?warnings
search() vs. match()
Python 提供了兩種不同的操作:基于 re.match() 檢查字符串開頭,或者 re.search() 檢查字符串的任意位置(默認Perl中的行為)。
例如
>>>>>>?re.match("c",?"abcdef")????#?No?match>>>?re.search("c",?"abcdef")???#?Match
在 search() 中,可以用 '^' 作為開始來限制匹配到字符串的首位
>>>>>>?re.match("c",?"abcdef")????#?No?match>>>?re.search("^c",?"abcdef")??#?No?match>>>?re.search("^a",?"abcdef")??#?Match
注意 MULTILINE 多行模式中函數 match() 只匹配字符串的開始,但使用 search() 和以 '^' 開始的正則表達式會匹配每行的開始
>>>>>>?re.match('X',?'A\nB\nX',?re.MULTILINE)??#?No?match>>>?re.search('^X',?'A\nB\nX',?re.MULTILINE)??#?Match
建立一個電話本
split() 將字符串用參數傳遞的樣式分隔開。這個方法對于轉換文本數據到易讀而且容易修改的數據結構,是很有用的,如下面的例子證明。
首先,這是輸入。通常它可能來自文件,這里我們使用三引號字符串語法:
>>>>>>?text?=?"""Ross?McFluff:?834.345.1254?155?Elm?Street......?Ronald?Heathmore:?892.345.3428?436?Finley?Avenue...?Frank?Burger:?925.541.7625?662?South?Dogwood?Way.........?Heather?Albrecht:?548.326.4584?919?Park?Place"""
條目用一個或者多個換行符分開。現在我們將字符串轉換為一個列表,每個非空行都有一個條目:
>>>?entries?=?re.split("\n+",?text)>>>?entries['Ross?McFluff:?834.345.1254?155?Elm?Street','Ronald?Heathmore:?892.345.3428?436?Finley?Avenue','Frank?Burger:?925.541.7625?662?South?Dogwood?Way','Heather?Albrecht:?548.326.4584?919?Park?Place']
最終,將每個條目分割為一個由名字、姓氏、電話號碼和地址組成的列表。我們為 split() 使用了 maxsplit 形參,因為地址中包含有被我們作為分割模式的空格符:
>>>?[re.split(":??",?entry,?3)?for?entry?in?entries][['Ross',?'McFluff',?'834.345.1254',?'155?Elm?Street'],['Ronald',?'Heathmore',?'892.345.3428',?'436?Finley?Avenue'],['Frank',?'Burger',?'925.541.7625',?'662?South?Dogwood?Way'],['Heather',?'Albrecht',?'548.326.4584',?'919?Park?Place']]
:? 樣式匹配姓后面的冒號,因此它不出現在結果列表中。如果 maxsplit 設置為 4 ,我們還可以從地址中獲取到房間號:
>>>?[re.split(":??",?entry,?4)?for?entry?in?entries][['Ross',?'McFluff',?'834.345.1254',?'155',?'Elm?Street'],['Ronald',?'Heathmore',?'892.345.3428',?'436',?'Finley?Avenue'],['Frank',?'Burger',?'925.541.7625',?'662',?'South?Dogwood?Way'],['Heather',?'Albrecht',?'548.326.4584',?'919',?'Park?Place']]
文字整理
sub() 替換字符串中出現的樣式的每一個實例。這個例子證明了使用 sub() 來整理文字,或者隨機化每個字符的位置,除了首位和末尾字符
>>>>>>?def?repl(m):...?????inner_word?=?list(m.group(2))...?????random.shuffle(inner_word)...?????return?m.group(1)?+?"".join(inner_word)?+?m.group(3)>>>?text?=?"Professor?Abdolmalek,?please?report?your?absences?promptly.">>>?re.sub(r"(\w)(\w+)(\w)",?repl,?text)'Poefsrosr?Aealmlobdk,?pslaee?reorpt?your?abnseces?plmrptoy.'>>>?re.sub(r"(\w)(\w+)(\w)",?repl,?text)'Pofsroser?Aodlambelk,?plasee?reoprt?yuor?asnebces?potlmrpy.'
找到所有副詞
findall() 匹配樣式 所有 的出現,不僅是像 search() 中的第一個匹配。比如,如果一個作者希望找到文字中的所有副詞,他可能會按照以下方法用 findall()
>>>>>>?text?=?"He?was?carefully?disguised?but?captured?quickly?by?police.">>>?re.findall(r"\w+ly",?text)['carefully',?'quickly']
找到所有副詞和位置
如果需要匹配樣式的更多信息, finditer() 可以起到作用,它提供了 匹配對象 作為返回值,而不是字符串。繼續上面的例子,如果一個作者希望找到所有副詞和它的位置,可以按照下面方法使用 finditer()
>>>>>>?text?=?"He?was?carefully?disguised?but?captured?quickly?by?police.">>>?for?m?in?re.finditer(r"\w+ly",?text):...?????print('%02d-%02d:?%s'?%?(m.start(),?m.end(),?m.group(0)))07-16:?carefully40-47:?quickly
原始字符記法
原始字符串記法 (r"text") 保持正則表達式正常。否則,每個正則式里的反斜杠('\') 都必須前綴一個反斜杠來轉義。比如,下面兩行代碼功能就是完全一致的
>>>>>>?re.match(r"\W(.)\1\W",?"?ff?")>>>?re.match("\\W(.)\\1\\W",?"?ff?")
當需要匹配一個字符反斜杠,它必須在正則表達式中轉義。在原始字符串記法,就是 r"\\"。否則就必須用 "\\\\",來表示同樣的意思
>>>>>>?re.match(r"\\",?r"\\")>>>?re.match("\\\\",?r"\\")
寫一個詞法分析器
一個 詞法器或詞法分析器 分析字符串,并分類成目錄組。這是寫一個編譯器或解釋器的第一步。
文字目錄是由正則表達式指定的。這個技術是通過將這些樣式合并為一個主正則式,并且循環匹配來實現的
import collectionsimport reToken = collections.namedtuple('Token', ['type', 'value', 'line', 'column'])def tokenize(code):keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}token_specification = [('NUMBER', ? r'\d+(\.\d*)?'), ?# Integer or decimal number('ASSIGN', ? r':='), ? ? ? ? ? # Assignment operator('END', ? ? ?r';'), ? ? ? ? ? ?# Statement terminator('ID', ? ? ? r'[A-Za-z]+'), ? ?# Identifiers('OP', ? ? ? r'[+\-*/]'), ? ? ?# Arithmetic operators('NEWLINE', ?r'\n'), ? ? ? ? ? # Line endings('SKIP', ? ? r'[ \t]+'), ? ? ? # Skip over spaces and tabs('MISMATCH', r'.'), ? ? ? ? ? ?# Any other character]tok_regex = '|'.join('(?P%s)' % pair for pair in token_specification)line_num = 1line_start = 0for mo in re.finditer(tok_regex, code):kind = mo.lastgroupvalue = mo.group()column = mo.start() - line_startif kind == 'NUMBER':value = float(value) if '.' in value else int(value)elif kind == 'ID' and value in keywords:kind = valueelif kind == 'NEWLINE':line_start = mo.end()line_num += 1continueelif kind == 'SKIP':continueelif kind == 'MISMATCH':raise RuntimeError(f'{value!r} unexpected on line {line_num}')yield Token(kind, value, line_num, column)statements = '''IF quantity THENtotal := total + price * quantity;tax := price * 0.05;ENDIF;'''for token in tokenize(statements):print(token)
這個詞法器產生以下輸出
Token(type='IF',?value='IF',?line=2,?column=4)Token(type='ID',?value='quantity',?line=2,?column=7)Token(type='THEN',?value='THEN',?line=2,?column=16)Token(type='ID',?value='total',?line=3,?column=8)Token(type='ASSIGN',?value=':=',?line=3,?column=14)Token(type='ID',?value='total',?line=3,?column=17)Token(type='OP',?value='+',?line=3,?column=23)Token(type='ID',?value='price',?line=3,?column=25)Token(type='OP',?value='*',?line=3,?column=31)Token(type='ID',?value='quantity',?line=3,?column=33)Token(type='END',?value=';',?line=3,?column=41)Token(type='ID',?value='tax',?line=4,?column=8)Token(type='ASSIGN',?value=':=',?line=4,?column=12)Token(type='ID',?value='price',?line=4,?column=15)Token(type='OP',?value='*',?line=4,?column=21)Token(type='NUMBER',?value=0.05,?line=4,?column=23)Token(type='END',?value=';',?line=4,?column=27)Token(type='ENDIF',?value='ENDIF',?line=5,?column=4)Token(type='END',?value=';',?line=5,?column=9)
總結
以上是生活随笔為你收集整理的python正则表达式处理txt_Python文本处理服务(re正则表达式例子)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高斯课堂数电讲义笔记_【法考经验贴】40
- 下一篇: 全球第一位“半机械人”去世 曾为对抗绝症