正規表示式的誤區

2021-06-16 06:39:03 字數 3095 閱讀 1207

正規表示式對一些應用程式來說是乙個強大的工具,但在有些時候它並不直觀而且有時它們不按你期望的執行。本節將指出一些最容易犯的常見錯誤。

使用字串方式

有時使用 re 模組是個錯誤。如果你匹配乙個固定的字串或單個的字元類,並且你沒有使用 re 的任何象 ignorecase 標誌的功能,那麼就沒有必要使用正規表示式了。字串有一些方法是對固定字串進行操作的,它們通常快很多,因為都是乙個個經過優化的c 小迴圈,用以代替大的、更具通用性的正規表示式引擎。

舉個用乙個固定字串替換另乙個的例子;如,你可以把 "deed" 替換成 "word"。re.sub() seems like the function to use for this, but consider the replace() method. 注意 replace() 也可以在單詞裡面進行替換,可以把 "swordfish" 變成 "sdeedfish",不過 re 也是可以做到的。(為了避免替換單詞的一部分,模式將寫成 \bword\b,這是為了要求 "word" 兩邊有乙個單詞邊界。這是個超出替換能力的工作)。

另乙個常見任務是從乙個字串中刪除單個字元或用另乙個字元來替代它。你也許可以用象 re.sub('\n',' ',s) 這樣來實現,但 translate() 能夠實現這兩個任務,而且比任何正規表示式操作起來更快。

總之,在使用 re 模組之前,先考慮一下你的問題是否可以用更快、更簡單的字串方法來解決。

match() vs search()

match() 函式只檢查 re 是否在字串開始處匹配,而 search() 則是掃瞄整個字串。記住這一區別是重要的。記住,match() 只報告一次成功的匹配,它將從 0 處開始;如果匹配不是從 0 開始的,match() 將不會報告它。

#!python

>>> print re.match('super', 'superstition').span()

(0, 5)

>>> print re.match('super', 'insuperable')

none

另一方面,search() 將掃瞄整個字串,並報告它找到的第乙個匹配。

#!python

>>> print re.search('super', 'superstition').span()

(0, 5)

>>> print re.search('super', 'insuperable').span()

(2, 7)

有時你可能傾向於使用 re.match(),只在re的前面部分新增 .* 。請盡量不要這麼做,最好採用 re.search() 代替之。正規表示式編譯器會對 res 做一些分析以便可以在查詢匹配時提高處理速度。乙個那樣的分析機會指出匹配的第乙個字元是什麼;舉個例子,模式 crow 必須從 "c" 開始匹配。分析機可以讓引擎快速掃瞄字串以找到開始字元,並只在 "c" 被發現後才開始全部匹配。

新增 .* 會使這個優化失敗,這就要掃瞄到字串尾部,然後回溯以找到 re 剩餘部分的匹配。使用 re.search() 代替。

貪婪 vs 不貪婪

當重複乙個正規表示式時,如用 a*,操作結果是盡可能多地匹配模式。當你試著匹配一對對稱的定界符,如 html 標誌中的尖括號時這個事實經常困擾你。匹配單個 html 標誌的模式不能正常工作,因為 .* 的本質是「貪婪」的

#!python

>>> s = 'title'

>>> len(s)

32>>> print re.match('<.*>', s).span()

(0, 32)

>>> print re.match('<.*>', s).group()

title

re 匹配 在 "" 中的 "<",.* 消耗掉子符串的剩餘部分。在 re 中保持更多的左,雖然 > 不能匹配在字串結尾,因此正規表示式必須乙個字元乙個字元地回溯,直到它找到 > 的匹配。最終的匹配從 "" 中的 ">",這並不是你所想要的結果。

在這種情況下,解決方案是使用不貪婪的限定符 *?、+?、?? 或 ?,盡可能匹配小的文字。在上面的例子裡, ">" 在第乙個 "<" 之後被立即嘗試,當它失敗時,引擎一次增加乙個字元,並在每步重試 ">"。這個處理將得到正確的結果:

#!python

>>> print re.match('<.*?>', s).group()

注意用正規表示式分析 html 或 xml 是痛苦的。變化混亂的模式將處理常見情況,但 html 和 xml 則是明顯會打破正規表示式的特殊情況;當你編寫乙個正規表示式去處理所有可能的情況時,模式將變得非常複雜。象這樣的任務用 html 或 xml 解析器。

不用 re.verbose

現在你可能注意到正規表示式的表示是十分緊湊,但它們非常不好讀。中度複雜的 res 可以變成反斜槓、圓括號和元字元的長長集合,以致於使它們很難讀懂。

在這些 res 中,當編譯正規表示式時指定 re.verbose 標誌是有幫助的,因為它允許你可以編輯正規表示式的格式使之更清楚。

re.verbose 標誌有這麼幾個作用。在正規表示式中不在字元類中的空白符被忽略。這就意味著象 dog | cat 這樣的表示式和可讀性差的 dog|cat 相同,但 [a b] 將匹配字元 "a"、"b" 或 空格。另外,你也可以把注釋放到 re 中;注釋是從 "#" 到下一行。當使用三引號字串時,可以使 res 格式更加乾淨:

#!python

pat = re.compile(r"""

\s* # skip leading whitespace

(?p[^:]+) # header name

\s* : # whitespace, and a colon

(?p.*?) # the header's value -- *? used to

# lose the following trailing whitespace

\s*$ # trailing whitespace to end-of-line

""", re.verbose)

這個要難讀得多:

#!python

pat = re.compile(r"\s*(?p[^:]+)\s*:(?p.*?)\s*$")

Java中正規表示式 誤區記錄

經常看見正規表示式 括號什麼什麼括號加,但是一直存在誤解,寫這個來做記錄 例如 scdn 官方解釋 乙個或者更多個 官方匹配模板集 我的誤區模板集 csdnbanabanacsdncsdncsdn 官方結果 csdn和csdncsdncsdn 我臆想中的結果 csdn和csdncsdn,csdncs...

正規表示式 正規表示式 總結

非負整數 d 正整數 0 9 1 9 0 9 非正整數 d 0 負整數 0 9 1 9 0 9 整數 d 非負浮點數 d d 正浮點數 0 9 0 9 1 9 0 9 0 9 1 9 0 9 0 9 0 9 1 9 0 9 非正浮點數 d d 0 0 負浮點數 正浮點數正則式 英文本串 a za z...

正規表示式 表示式

網域名稱 a za z0 9 a za z0 9 a za z0 9 a za z0 9 interneturl a za z s 或 http w w w 手機號碼 13 0 9 14 5 7 15 0 1 2 3 5 6 7 8 9 18 0 1 2 3 5 6 7 8 9 d 號碼 x x x...