<input id="ohw05"></input>
  • <table id="ohw05"><menu id="ohw05"></menu></table>
  • <var id="ohw05"></var>
  • <code id="ohw05"><cite id="ohw05"></cite></code>
    <label id="ohw05"></label>
    <var id="ohw05"></var>
  • 說說正則表達式

    1 引言

    網上說正則式的文章很多,剛開始有同事提議寫寫正則式,我實際上是有點拒絕的,畢竟看看別人的文章基本上就能滿足需求了,純粹做搬運工有點心有不甘,但要寫的有新意確實也很困難。

    但回想起自己剛接觸正則表達式時的窘境,也看到csdn上還有一些沒什么油鹽的正則表達式文章居然還開收費,覺得還是有一些可說的。

    2 正則表達式的使用場景

    正則表達式,英文全稱是regular expression或者rational expression,從字面意思看regular表示常規的,合規的,正常的等含義;rational表示合理的,理性的等含義。

    這個概念起源于數學家Stephen Cole Kleene1951年在《神經網絡和有限自動機的事件表達》定義了一種新的數學描述語言regular events,該文章中引入了EvF, EF, E*F等表達式,這也算是正則表達式的雛形。

    常規使用正則式的場景主要有編程語言、命令行、文本編輯器這三種。

    2.1 編程語言

    編程語言不用多說,為了實現某個功能,功能里面可能就要求支持正則匹配進行搜索和替換。

    基本上大家現在還在使用的高級語言都支持正則表達式,部分是編程語言原生就支持,部分需要使用第三方的類庫方式來支持。

    例如:python,bash,c++,java,php,perl等。

    2.2 命令行界面

    這個和編程語言類似,主要是各種shell,和編程語言的差別無非是即寫即用。shell可以認為是一個字符流的執行實體,這個字符流中任意一個全集或者子集都可以應用到正則表達式。里面使用正則表達式最突出的是linux的三件套,grep、sed和awk。

    2.3 各種編輯器

    很多文本編輯器的搜索和替換,都支持正則表達式(很遺憾,office還不支持正則表達式),例如常用的notepad++,sublime text,vscode等等。

    在處理一個文本文件的時候,會點正則表達式經常會有事半功倍的效果。

    舉個例子,很多web頁面對右鍵事件和選擇事件做了捕獲,這使得正常的拷貝動作,即使是文本拷貝,在對應網站上沒法實現,用開發者工具類似的功能能看到web的源代碼,并將對應段的html代碼拷貝出來,但html代碼中有大量的tag,會影響我們獲取純文本,使用下面的正則表達式可以匹配所有tag,替換成空就可以達到保留純文本的目的:

    <[^>]*>

     

    3 正則表達式的風格

    現在大家使用的正則表達式已經不是Stephen Cole Kleene定義的最原始版本的regular events了,比較普遍的主要有兩種風格,POSIX和PCRE。

    3.1 POSIX Extended 1003.2

    和網絡協議棧里面的ISO和TCP/IP對應,正則表達式也存在一個國際標準和一個事實標準。

    POSIX Extended 1003.2是電氣和電子工程師協會(IEEE)制定的,相當于國際標準,但實際上各種編程語言對它的支持并不好,或者有些是部分支持。Bash默認的是POSIX風格的正則表達式,但部分命令,例如grep可以使用-E(POSIX Extended 1003.2),-G(BRE)和-P(PCRE)來指定不同風格的正則表達式。

    3.2 PCRE

    PCRE相當于事實標準,基本上絕大多數編程語言都支持PCRE,當然最早在編程語言中支持正則表達式的Perl更是因為PCRE在文本處理中一騎絕塵,很多后起的編程語言,都依賴Perl的相關設計來指定自己的文本處理規則。

    Python編程語言和notepad++/sublime text這兩種編輯器是perl風格的正則表達式。有一些編程語言,例如PHP,2種風格都支持。

     

    3.3 其他風格

    由于POSIX Extended 1003.2沒有對多字節字符的說明,PHP做POSIX標準(ereg)的基礎上,還支持了多字節字符的POSIX標準(mb_ereg)。

    PCRE依賴修正符u來支持UTF-8格式的正則表達式。

     

    3.4 POSIX Extended 1003.2和PCRE的差異

    3.4.1 定界符

    POSIX Extended 1003.2沒有定界符,PCRE有定界符,并且除了字母、數字和反斜線\以外的任何字符都可以做定界符。

    為什么POSIX Extended 1003.2沒有定界符?

    這要從PCRE為什么有定界符來說起,PCRE引入定界符主要是為了給修正符一個合適的位置,也就是說一對定界符包圍的字符串之外的字符就是修正符,POSIX Extended 1003.2不支持修正符,所以也沒有必要支持定界符。

    3.4.2 修正符

    PCRE中支持11種修正符,方便正則表達式的使用更加靈活:

    i(忽略大小寫),m(多行修正),s(.包含換行符),x(忽略空白字符,轉義的空白除外),e(支持逆向引用),A(強制從開頭開始匹配),D($匹配換行符,m設置的話該參數無效),S(加速匹配),U(?使用貪婪模式),X(待擴展),u(默認UTF-8)

    3.4.3 POSIX Extended 1003.2的類型匹配

    [:upper:]:匹配所有的大寫字母

    [:lower:]:匹配所有的小寫字母

    [:alpha:]:匹配所有的字母

    [:alnum:]:匹配所有的字母和數字

    [:digit:]:匹配所有的數字

    [:xdigit:]:匹配所有的十六進制字符,等價于[0-9A-Fa-f]

    [:punct:]:匹配所有的標點符號,等價于[.,"'?!;:]

    [:blank:]:匹配空格和TAB,等價于[ \t]

    [:space:]:匹配所有的空白字符,等價于[ \t\n\r\f\v]

    [:cntrl:]:匹配所有ASCII 0到31之間的控制符。

    [:graph:]:匹配所有的可打印字符,等價于:[^ \t\n\r\f\v]

    [:print:]:匹配所有的可打印字符和空格,等價于:[^\t\n\r\f\v]

    [.c.]:未定義

    [=c=]:未定義

    [:<:]:匹配單詞的開始

    [:>:]:匹配單詞的結尾

    3.4.4 PCRE的類型匹配

    \a alarm,即 BEL字符(’0)

    \cx "control-x",其中 x 是任意字符

    \e escape(’0B)

    \f 換頁符 formfeed(’0C)

    \n 換行符 newline(’0A)

    \r 回車符 carriage return(’0D)

    \t 制表符 tab(’0)

    \xhh 十六進制代碼為 hh 的字符

    \ddd 八進制代碼為 ddd的字符,或 backreference

    \d 任一十進制數字

    \D 任一非十進制數的字符

    \s 任一空白字符

    \S 任一非空白字符

    \w 任一數字、字母或下劃線的字符

    \W 任一非數字、字母或下劃線的字符

    \b 字分界線

    \B 非字分界線

    \A 目標的開頭(獨立于多行模式)

    \Z 目標的結尾或位于結尾的換行符前(獨立于多行模式)

    \z 目標的結尾(獨立于多行模式)

    \G 目標中的第一個匹配位置

    4 一個復雜模式匹配的替換過程

    常規的查找相對都比較簡單,只要歸納總結一下字符流的規律就可以形成匹配的正則表達式,常規的提取和替換也支持對第幾個匹配項的提取,這在模式匹配中也非常常用。

     

    如果通過某種通配模式匹配下來的字符經過一定復雜處理之后再進行替換怎么處理?一些編程語言還提供了回調的方式進行替換。

    例如python手冊re — Regular expression operations — Python 3.9.7 documentation里面的這個re模塊的例子:

    >>> import re
    >>> def dashrepl(matchobj):
    ...     if matchobj.group(0) == '-'return ' '
    ...     elsereturn '-'
    ...
    >>> re.sub('-{1,2}', dashrepl, 'pro----gram-files')
    'pro--gram files'
    >>> re.sub('-{1,}', dashrepl, 'pro----gram-files')
    'pro-gram files'

    其中dashrepl定義了一個回調函數,對于使用'-{1,2}'匹配一個或者兩個-的情況下,分別針對單個-或者兩個-的情況替換為空或者-;而在使用'-{1,}'匹配一個或者多個-的情況下,分別針對單個-或者多個-的情況替換為空或者-。

     

    5 參考資料

    5.1  posix和perl標準的正則表達式區別_lcy_ltpsr的專欄-CSDN博客_posix和perl標準的正則表達式區別

    5.2 Representation of Events in Nerve Nets and Finite Automata | RAND

    5.3 re — Regular expression operations — Python 3.9.7 documentation

    posted @ 2021-09-02 18:48  周榮華  閱讀(620)  評論(0編輯  收藏  舉報
    国产美女a做受大片观看