day5模塊學習--re正則模塊

来源:http://www.cnblogs.com/gengcx/archive/2017/07/26/7231973.html
-Advertisement-
Play Games

1. 正則表達式基礎 1.1. 簡單介紹 正則表達式並不是Python的一部分。正則表達式是用於處理字元串的強大工具,擁有自己獨特的語法以及一個獨立的處理引擎,效率上可能不如str自帶的方法,但功能十分強大。得益於這一點,在提供了正則表達式的語言里,正則表達式的語法都是一樣的,區別隻在於不同的編程語 ...


1. 正則表達式基礎

1.1. 簡單介紹

    正則表達式並不是Python的一部分。正則表達式是用於處理字元串的強大工具,擁有自己獨特的語法以及一個獨立的處理引擎,效率上可能不如str自帶的方法,但功能十分強大。得益於這一點,在提供了正則表達式的語言里,正則表達式的語法都是一樣的,區別隻在於不同的編程語言實現支持的語法數量不同;但不用擔心,不被支持的語法通常是不常用的部分。如果已經在其他語言里使用過正則表達式,只需要簡單看一看就可以上手了。

    下圖展示了使用正則表達式進行匹配的流程:  http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html

   

 

    正則表達式的大致匹配過程是:依次拿出表達式和文本中的字元比較,如果每一個字元都能匹配,則匹配成功;一旦有匹配不成功的字元則匹配失敗。如果表達式中有量詞或邊界,這個過程會稍微有一些不同,但也是很好理解的,看下圖中的示例以及自己多使用幾次就能明白。

    下圖列出了Python支持的正則表達式元字元和語法:

   

    1.”.“匹配任意除換行符以外的字元

    >>> string = "abafsdafd\nafdasfd"         #包含換行符
  >>> string1 = "adfasdfadfasdfwer12345656耿"     #不包含換行符
  >>> import re  
  >>> m = re.search(".+",string)           #驗證是否可以匹配換行符
  >>> m.group()
  'abafsdafd'

    >>> n = re.search(".+",string1)
  >>> n.group()
  'adfasdfadfasdfwer12345656耿'
    從上面輸出結果可以看出,”.“是匹配任意除了換行符的字元。遇到"\n"換行符即終止匹配。

    2.”\"轉義字元

    轉義字元,使後一個字元改變原來的意思。如果字元串中有*號需要匹配,可以使用\*或者字元集[*],"a\.c"代表匹配a.c  "a\\c"代表匹配a\c

    >>> str_num = "22.567979mafdasdf"
  >>> m = re.search("\d+\.\d+",str_num)
  >>> m.group()
  '22.567979'
    我們知道,"."在python中代表的含義是除了"\n"之外的所有字元,如果這裡不進行轉義的話,匹配出來的就是任意非"\n"字元,因此要使用"\"進行轉義。

    >>> string = "dfafdasfd\fafdasfda"
  >>> string
  'dfafdasfd\x0cafdasfda'
    在python中,如果字元串中包含"\",有時候會顯示不出來,或者修改後面的內容,把別人改變了,這個不知道在Linux平臺上是怎麼回事。

    3.[...]字元集(字元類)   
    [...]:字元集(字元類)對應的位置可以是字元集中任意字元。字元集中的字元可以逐個列出[0,1,2,3,4,5,6,7,8,9],也可以給出範圍[0-9]。第一個字元集如果是^表示取反,如[^abc]表示不是abc的其他字元。

    所有的特殊字元在字元集中都失去其原有的特殊意義。在字元集中如果要使用]、或^,可以在前面加上"\"反斜杠,或把]\、-放在第一個字元,把^放在非第一個字元。

    >>> string = "dafdafdasf[adfas^fad"

    >>> m = re.search("[a-z]+\[",string)
  >>> m.group()
  'dafdafdasf['
    從上面腳本可以看出,如果要匹配[要在前面加上"\"轉義字元。

    >>> m = re.search("\w+[[]",string)      (1)在字元集中匹配"["
  >>> m.group()
  'dafdafdasf['
    >>> n = re.search("w+[\[]",string)      (2)轉義匹配,驗證在字元集中匹配[是否需要加[\]
  >>> n.group()
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  AttributeError: 'NoneType' object has no attribute 'group'
    在字元集中如果要使用]、或^,可以在前面加上"\"反斜杠,或把]\、-放在第一個字元,把^放在非第一個字元。
    預定義字元集

    1.\d數字

    >>> m = re.search("\d",string)
  >>> m.group()
  '1'
    \d是匹配數字,等價於[0-9]
    2.\D非數字       等價於[^\d]

    >>> string = "dfaMNA12581耿fa"
  >>> m = re.search("\D",string)
  >>> m.group()
  'd'
  >>> n = re.search("[^\d]",string)
  >>> n.group()
  'd'

    >>> l = re.search("[^0-9]",string)
  >>> l.group()
  'd'
    從上面可以看出,“\D”是用來匹配非數字的,匹配除了數字0-9意外的任意字元,等價於[^0-9]或[^\d]
    3.\s空白字元     [<空格>\r\t\n\f\v]

    “\s”是匹配任意非空字元,如[<空格>\r\t\n\f\v]等,實例如下:

    >>> m = re.search("\s+",string)     #\s進行匹配空白字元
  >>> m.group()
  ' \t \n \x0c \x0b \r'
    從上面可以看出,\s是匹配任意空白字元,如空格、\r、\t、\n、\f、\v等

    4.\S非空白字元     \S與\s正好相反,是匹配任意非空字元。等價於[^\s]匹配任意非空字元

    >>> string = "faMM耿 \t \n \f \v \rDASDF"
    >>> n = re.search("\S+",string)
  >>> n.group()
  'faMM耿'
    從上面可以看出"\S"是匹配任意非空字元,遇到空的字元即停止了,匹配任意非空字元,"."匹配任意字元,除了換行符之外。

    >>> m = re.search(".+",string)
  >>> m.group()
  'faMM耿 \t '
    從上面看出,“\S”和“.”還是有差別的,一個是任意非空字元,一個是匹配任意除了"\n"意外任意非空字元。

    5.\w 單詞字元[A-Z0-9a-z_]   
    \w是匹配單詞字元,下麵來看下能不能匹配漢字或其他:

    >>> string = "faMM耿 \t \n \f \v \rDASDF"

    >>> m = re.search("\w+",string)
  >>> m.group()
  'faMM耿'                (1)腳本

    >>> format_string = "fdMM更KKMM長 /大MM \n \tMMKDSI"
  >>> m = re.search("\w+",format_string)
  >>> m.group()
  'fdMM更KKMM長'          (2)腳本

    可以看出,"\w"是可以匹配漢字的,不能匹配空格,換行符這些,但是能夠匹配漢字。

    6.\W       等價於非單詞字元 [^\w]  

    >>> import re
  >>> string = "naefda曾 LmKDS 1316547\n\t\r@@3$&^$"
  >>> m = re.search("\W+",string)

    >>> m.group()
  ' '

    從上面可以看出"\W "匹配出來了空,說明" "不是單詞字元,"\W"是匹配非單詞字元。

    數量詞(用在字元或(...)之後)

    1."*"       匹配前一個字元0或無限次       前一個字元

    "*"是匹配前一個字元0或無限次

    >>> import re
  >>> string = "naefda曾 LmKDS 1316547\n\t\r@@3$&^$"
    >>> m = re.search("\w*",string)
  >>> m.group()
  'naefda曾'
  >>> n = re.search("\d*",string)
  >>> n.group()
  ''

    >>> n = re.search("耿",string)
  >>> n
  >>> n.group()
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  AttributeError: 'NoneType' object has no attribute 'group'

    從上面腳本代碼可以看出,當使用*要查找的字元在開頭的時候就會匹配到,在中間就匹配不到。這種懶惰的匹配方式,如果其他情況下匹配不到,則會返回錯誤。

    2.“+”    匹配前一個字元一次或無限次    前一個字元(牢記,只是匹配前面一個)

    >>> import re
  >>> string = "naefda曾 LmKDS 1316547\n\t\r@@3$&^$"
    >>> m = re.search("\w+",string)
  >>> m.group()
  'naefda曾'
  >>> n = re.search("\s+",string)
  >>> n.group()
  ' '
  >>> d = re.search("更",string)
  >>> d.group()
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  AttributeError: 'NoneType' object has no attribute 'group'
    從上面可以看出,"+"是匹配前一個字元一次或無限次,如果匹配不到,則返回None

    3."?"   匹配前一個字元0次或一次        前一個字元(牢記,只是匹配前面一個)

    >>> import re
  >>> string = "naefda曾 LmKDS 1316547\n\t\r@@3$&^$"
  >>> m = re.search("\w?",string)
  >>> m.group()
  'n'
  >>> n = re.search("f?",string)
  >>> n.group()
  ''
    從上面可以看出,?是以貪婪的方式進行匹配。?是匹配前一個字元0次或1次。從上面的例子中發現一個問題,即"?"和"*"都是從頭開始進行匹配,如果開頭匹配不到,就返回"",等價於如果使用search()出現”?"和“*”等價於使用match()從頭開始匹配,找不到則不找了,不一樣的是match()返回的是None,而seach()返回的是""。

    4.{m}   代表匹配前一個字元m次        前一個字元(牢記,只是匹配前面一個)

    >>> import re

    >>> string = "dafMM\n更1134657Qqcd m,l#!"
  >>> m = re.search("\d{4}",string)        #代表匹配數字四次
  >>> m.group()
  '1134'

    >>> n = re.search("\d{10}",string)
  >>> n.group()
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  AttributeError: 'NoneType' object has no attribute 'group'

    從上面可以看出,如果匹配不到,則返回None;{m}是代表匹配前一個字元m次,要註意在匹配的時候,我們可以像下麵一樣設定一個匹配區間,這樣就不會出現匹配超標的情況。

    5.{m,n}    匹配一個字元m次至n次         前一個字元(牢記,只是匹配前面一個)

    m和n可以省略,如省略m({,n})則匹配0到n次;若省略n({m,}),則匹配m至無限次。

    >>> import re

    >>> string = "dafMM\n更1134657Qqcd m,l#!"

   >>> m = re.search("\d{1,10}",string)
  >>> m.group()
  '1134657'
  >>> n = re.search("\d{,5}",string)
  >>> n.group()
  ''
  >>> d = re.search("\d{4,}",string)
  >>> d.group()
  '1134657'
    從上面可以看出,{m,n}是匹配在一個範圍內的個數,但是我們也發現了一個問題,千萬不要讓正則表達式匹配包含0次的情況,一旦匹配0次,那麼就會出現如果開頭匹配不到之後,就不匹配的情況,直接返回""。

    *? +? ?? {m,n}?使*,+,?,{m,n}變成非貪婪模式。

    邊界匹配

    1.^  匹配字元串開頭,在多行模式中,匹配第一行的開頭

    >>> import re

    >>> string = "dafMM\n更1134657Qqcd m,l#!"

    >>> m = re.search("^da",string)
  >>> m.group()
  'da'

    開頭匹配,相當於使用match()進行匹配了。

    2.$    匹配字元串末尾,在多行模式中匹配每一行的末尾  

    >>> import re

    >>> string = "dafMM\n更1134657Qqcd m,l#!"

    >>> m = re.search("#!",string)
  >>> m.group()
  '#!'
    "$"是匹配字元串的末尾,不管前面,值匹配末尾是否是要匹配的內容。

    3.\A    僅匹配字元串開頭

    >>> import re

    >>> string = "dafMM\n更1134657Qqcd m,l#!"

    >>> m = re.search("\Adaf",string)
  >>> m.group()
  'daf'
    “\A”是僅匹配字元串開頭,即僅僅從字元串的開頭進行匹配。
    4.\Z    僅匹配字元串末尾

    >>> import re

    >>> string = "dafMM\n更1134657Qqcd m,l#!"

    >>> n = re.search("l#!",string)
  >>> n.group()
  'l#!'
    "\Z"是僅匹配字元串末尾,僅從末尾進行匹配,可能\Z和$的區別就是,$是匹配每行的末尾,而\Z是僅匹配字元串的末尾。

    5.\b   匹配\w和\W之間的字元   

    6.\B    匹配非\w和\W之間的字元 即[^\b]   

    邏輯分組

    1.“|”   代表左右表達式任意匹配一個

    它總是先嘗試匹配左邊的表達式,一旦成功則跳過右邊的表達式。如果|沒有被包含在()中,則它的範圍是整個正則表達式

    >>> import re
  >>> m = re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict()
  >>> m
  {'city': '81', 'birthday': '1993', 'province': '3714'}

    可以依次分組匹配,生成一個字典,groupdict(),分組匹配,給匹配到的字元串起名字。

1.2. 數量詞的貪婪模式與非貪婪模式

  正則表達式通常用於在文本中查找匹配的字元串。Python里數量詞預設是貪婪的(在少數語言里也可能是預設非貪婪),總是嘗試匹配儘可能多的字元;非貪婪的則相反,總是嘗試匹配儘可能少的字元。例如:正則表達式"ab*"如果用於查找"abbbc",將找到"abbb"。而如果使用非貪婪的數量詞"ab*?",將找到"a"。

1.3. 反斜杠的困擾

    與大多數編程語言相同,正則表達式里使用"\"作為轉義字元,這就可能造成反斜杠困擾。假如你需要匹配文本中的字元"\",那麼使用編程語言表示的正則表達式里將需要4個反斜杠"\\\\":前兩個和後兩個分別用於在編程語言里轉義成反斜杠,轉換成兩個反斜杠後再在正則表達式里轉義成一個反斜杠。Python里的原生字元串很好地解決了這個問題,這個例子中的正則表達式可以使用r"\\"表示。同樣,匹配一個數字的"\\d"可以寫成r"\d"有了原生字元串,你再也不用擔心是不是漏寫了反斜杠,寫出來的表達式也更直觀。

 

1.4. 匹配模式

    正則表達式提供了一些可用的匹配模式,比如忽略大小寫、多行匹配等,這部分內容將在Pattern類的工廠方法re.compile(pattern[, flags])中一起介紹。

2. re模塊     
    2.1. 開始使用re   
    Python通過re模塊提供對正則表達式的支持。使用re的一般步驟是先將正則表達式的字元串形式編譯為Pattern實例,然後使用Pattern實例處理文本並獲得匹配結果(一個Match實例),最後使用Match實例獲得信息,進行其他的操作。 

import re

#將正則表達式編譯成Pattern對象
pattern = re.compile(r'hello')

#使用pattern匹配文本,獲得匹配結果,無法匹配時將返回None
match = pattern.match("hello world!")
if match:
    #使用match獲得分組信息
    print(match.group())

 

    上面正則匹配中,首先進行了編譯,編譯成正則格式,然後進行匹配。

    re.compile(strPattern[, flag]):

    這個方法是Pattern類的工廠方法,用於將字元串形式的正則表達式編譯為Pattern對象。 第二個參數flag是匹配模式,取值可以使用按位或運算符'|'表示同時生效,比如re.I | re.M。另外,你也可以在regex字元串中指定模式,比如re.compile('pattern', re.I | re.M)與re.compile('(?im)pattern')是等價的。
可選值有:

    re模塊還提供了一個方法escape(string),用於將string中的正則表達式元字元如*/+/?等之前加上轉義符再返回,在需要大量匹配元字元時有那麼一點用。

    2.2. Match  
  >>> string = "aafaaMMaaaa"
  >>> m = re.search("aa?",string)
  >>> m.group()
  'aa'
  >>> n = re.search("aaa?",string)
  >>> n.group()
  'aa'
  >>> d = re.search("aaaa?",string)
  >>> d.group()
  'aaaa'
    上面代碼中,"?"的作用是匹配前一個字元,就是這個正則符號前面的那個字元0次或一次。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • /// /// 顏色擴展類 /// public static class ColorExtensions { /// /// .NET預定義的系統顏色緩存列表 /// private static readonly Dictionary ColorCache; /// /// 擁有相同顏色代碼值的... ...
  • 單例模式是設計模式中最簡單的形式之一。這一模式的目的是使得類的一個對象成為系統中的唯一實例。對於系統中的某些類來說,只有一個實例很重要,例如,一個系統中可以存在多個列印任務,但是只能有一個正在工作的任務;一個系統只能有一個視窗管理器或文件系統;一個系統只能有一個計時工具或ID(序號)生成器。 顯然單 ...
  • 能過資料庫的讀寫分離和使用NoSQL,以及搜索引擎後,能夠降低主庫的壓力,解決數據存儲方面的問題,不過隨著業務的繼續發展,我們的資料庫主庫還是會遇到性能瓶頸,所以為了減小資料庫主庫的壓力,我們有資料庫垂直拆分和水平拆分兩種方式。 資料庫拆分 資料庫拆分有兩種方法,垂直拆分和水平拆分。 垂直拆分 垂直 ...
  • Visual Studio 沒有提供此功能,只能用正則表達式,具體做法如下: 一、ctrl+ H 打開替換框 二、在替換框中的源中輸入 ^(?([^\r\n])\s)*\r?$\r?\n 圖如下: 完畢 ...
  • 這是什麼加密?可以吃嗎? 今天的給大家分享的應該是BASE64、MD5、AES演算法共同實現的吧,不過加密後體積會變大些,他不可以吃 一、概述 加密的流程大概就是醬紫的: 原文→BASE64編碼 →AES加密 得到密文 密碼→MD5加密 解密的流程大概是醬紫: 密碼 → MD5加密 → BASE64解 ...
  • java ee 中struts2中struts.xml中result標簽 ...
  • 1.package標簽下主要的點在namespace和name,extend上 extend 一般繼承自struts-default.xml下,繼承其攔截器及一些功能,這個已在本人的攔截器一文中有講到 namespace,主要用於約束訪問地址action前的路徑,比如http://www.baidu ...
  • 本節探討Java 8中的函數式數據處理 - Stream API,它能大大簡化常見的集合數據操作,怎麼做到的呢? ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...