python聖鬥士(十七) 令人欲罷不能的正則

2021-08-10 18:59:30 字數 2894 閱讀 3186

字串是程式設計時涉及到的最多的一種資料結構,對字串進行操作的需求幾乎無處不在。比如判斷乙個字串是否是合法的email位址,雖然可以程式設計提取@前後的子串,再分別判斷是否是單詞和網域名稱,但這樣做不但麻煩,而且**難以復用。

正規表示式是一種用來匹配字串的強有力的**。它的設計思想是用一種描述性的語言來給字串定義乙個規則,凡是符合規則的字串,我們就認為它「匹配」了,否則,該字串就是不合法的。

所以我們判斷乙個字串是否是合法的email的方法是:

建立乙個匹配email的正規表示式;

用該正規表示式去匹配使用者的輸入來判斷是否合法。

因為正規表示式也是用字串表示的,所以,我們要首先了解如何用字元來描述字元。

在正規表示式中,如果直接給出字元,就是精確匹配。用\d可以匹配乙個數字,\w可以匹配乙個字母或數字,所以:

'00\d'可以匹配'007',但無法匹配'00a';

'\d\d\d'可以匹配'010';

'\w\w\d'可以匹配'py3';

.可以匹配任意字元,所以:

'py.'可以匹配'pyc'、'pyo'、'py!'等等。
要匹配變長的字元,在正規表示式中,用*表示任意個字元(包括0個),用+表示至少乙個字元,用?表示0個或1個字元,用表示n個字元,用表示n-m個字元:

來看乙個複雜的例子:\d\s+\d。

我們來從左到右解讀一下:

\d表示匹配3個數字,例如'010';

\s可以匹配乙個空格(也包括tab等空白符),所以\s+表示至少有乙個空格,例如匹配' ',' '等;

\d表示3-8個數字,例如'1234567'。

綜合起來,上面的正規表示式可以匹配以任意個空格隔開的帶區號的**號碼。

如果要匹配』010-12345』這樣的號碼呢?由於』-『是特殊字元,在正規表示式中,要用』\』轉義,所以,上面的正則是\d-\d。

但是,仍然無法匹配』010 - 12345』,因為帶有空格。所以我們需要更複雜的匹配方式。

python中關於正則的模組是re

import re

re.findall(r'abc$','abcd')

//['abc']

re.findall

//返回匹配到的所有子串並返回列表,r表示後面所跟的為原字串。

re.match()

//從開始位置開始匹配,一旦出現不符合正規表示式的情況則匹配失敗。

re.search()

//匹配整個字串,如果找到乙個匹配則返回乙個物件。

re.sub()

//替換

re.sub(r'a','a','abcabaab')

//'abcabaab'

為什麼要加r:r是raw(原始)的意思。因為在表示字串中有一些轉義符,如表示回車』\n』。如果要表示\表需要寫為』\\』。但如果我就是需要表示乙個』\』+』n』,不用r方式要寫為:』\\n』。但使用r方式則為r』\n』這樣清晰多了。所以一般情況下我們都會加上r。

p=re.compile(r』abc』) 編譯生成乙個正則物件

p=re.compile(r』g』,re.i)

p.findall(『aaabcacac』) 呼叫方法

//[『abc』]

^(\d)-(\d)$分別定義了兩個組,可以直接從匹配的字串中提取出區號和本地號碼:

m = re.match(r』^(\d)-(\d)$』, 『010-12345』)

m //<_sre.sre_match object at 0x1026fb3e8>

m.group(0)

『010-12345』

m.group(1)

//』010』

m.group(2)

//』12345』

如果正規表示式中定義了組,就可以在match物件上用group()方法提取出子串來。

注意到group(0)永遠是原始字串,group(1)、group(2)……表示第1、2、……個子串。

提取子串非常有用。來看乙個更**的例子:

t = 『19:05:30』

m = re.match(r』^(0[0-9]|1[0-9]|2[0-3]|[0-9]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9]):(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$』, t)

m.groups()

(『19』, 『05』, 『30』)

這個正規表示式可以直接識別合法的時間。但是有些時候,用正規表示式也無法做到完全驗證,比如識別日期:

『^(0[1-9]|1[0-2]|[0-9])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]|[0-9])$』

對於』2-30』,』4-31』這樣的非法日期,用正則還是識別不了,或者說寫出來非常困難,這時就需要程式配合識別了。

最後需要特別指出的是,正則匹配預設是貪婪匹配,也就是匹配盡可能多的字元。舉例如下,匹配出數字後面的0:

re.match(r』^(\d+)(0*)$』, 『102300』).groups()

(『102300』, 」)

由於\d+採用貪婪匹配,直接把後面的0全部匹配了,結果0*只能匹配空字串了。

必須讓\d+採用非貪婪匹配(也就是盡可能少匹配),才能把後面的0匹配出來,加個?就可以讓\d+採用非貪婪匹配:

re.match(r』^(\d+?)(0*)$』, 『102300』).groups()

(『1023』, 『00』)

聖鬥士星矢手遊怎麼在電腦上玩 聖鬥士星矢電腦版教程

聖鬥士星矢 手遊不僅拿到了漫畫原作者車田正美的授權,成為車田正美直接授權的第乙個中國遊戲。在此基礎上,遊戲在許多方面都對漫畫經典元素進行了還原,不僅有青銅五小強初次較量的銀河擂台賽 爭分奪秒的 十二宮等經典戰鬥劇情,還有薩爾娜為星矢抵擋獅子座的拳頭 一輝與愛絲美拉達的愛情故事等等,深刻再現了那些聖迷...

python 令人抓狂的編碼問題

執行以下程式 usr bin env python coding utf 8 file open all hanzi.txt wb listhz n 0for ch in xrange 0x4e00,0x9fa6 print unichr ch file.write unichr ch 此行出錯。正...

python 學習(十七)之函式

一 python包括內建函式和使用者自定義函式。1.內建函式包括 2.使用者自定義函式 定義乙個實現所要實現某些功能的函式。二 使用者自定義函式 規則 語法 def functionname parameters 函式 文件字串 function suite 函式體 return expressio...