乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      對話 UNIX,第 9 部分: 正則表達式

       jijo 2008-08-04

      2007 年 5 月 28 日

      幾乎所有重要問題都需要從無用數(shù)據(jù)中過濾出有用數(shù)據(jù)。了解大量的 UNIX? 命令行實用工具如何使用正則表達式 來去蕪取精。

      非常奇怪,直到今天我仍然能重復(fù)周六早上的經(jīng)典歌曲“Conjunction Junction”。這是好事(看了太多電視)還是壞事(也許是我現(xiàn)在職業(yè)的先兆)仍然有待討論。不管怎樣,這首小調(diào)在歡快的節(jié)奏下傳遞了基本的信息。

      我還沒有為學(xué)習(xí) UNIX 構(gòu)想出與“Conjunction Junction”相似的作品,但是我會在未來的幾個月里嘗試親手編寫這樣的歌曲。與此同時,趁著快樂回憶所帶來的好心情,我們繼續(xù)以 Schoolhouse 搖滾的傳統(tǒng)學(xué)習(xí)方式攻克命令行。

      現(xiàn)在開始上課。吐出嘴里的口香糖,回到您的座位上,然后拿出一根二號鉛筆。還有您,Spicoli。

      模仿秀

      您可以將 UNIX 命令行看作是一句話:

      • 可執(zhí)行命令,如 catls,是動詞——操作。
      • 命令的輸出是名詞——要查閱或使用的數(shù)據(jù)。
      • Shell 操作符,如 |(管道)或 >(重定向標準輸出),是連詞——用于連接句子。

      例如,命令行:ls -A | wc -l 用于計算當(dāng)前目錄下的條目數(shù)(忽略特殊條目 ...),它包含兩個句子。第一個句子 ls -A 是動詞結(jié)構(gòu),列舉當(dāng)前目錄下的內(nèi)容,第二個句子 wc -l 是另一個動詞結(jié)構(gòu),用于計算行數(shù)。第一個句子輸出的結(jié)果作為第二個句子的輸入,并由連接詞(管道)連接這兩個句子。

      在本系列文章以及其他文章中展示的許多您可能已經(jīng)學(xué)習(xí)過的命令行句式都具有這種句子結(jié)構(gòu)。

      但是,如果缺少了文法上的修飾語,命令行將顯得不專業(yè)。當(dāng)然,基本句子也能完成工作,但是這樣顯得不優(yōu)美。(在此對高中英語演唱二人組 Rad 女士和 Perlstein 女士表示歉意。)解決更有趣的問題需要用到形容詞。

      幾乎所有重要問題都需要從無用數(shù)據(jù)中過濾出有用數(shù)據(jù)。雖然屬性的數(shù)量和種類會有所不同,但是每種方案都通過某種方式(形式或格式),隱式或顯式地描述了它要查找并處理的信息,從而生成另外一種形式的其他信息。

      在命令行中,正則表達式 的作用相當(dāng)于形容詞——一種描述或限定詞。在應(yīng)用到輸出時,正則表達式可辨別相關(guān)數(shù)據(jù)和無關(guān)數(shù)據(jù)。

      標點概述

      讓我們看一個示例問題。

      grep 實用工具逐行過濾輸入并尋找匹配。grep 的最簡單應(yīng)用是打印那些包含與某個模式匹配的文本的行。grep 可以查找具有固定順序的字符組合,甚至可以通過使用 -i 選項來忽略大小寫。

      因此,假定文件 heroes.txt 包含以下行:

      Catwoman
                              Batman
                              The Tick
                              Spider Man
                              Black Cat
                              Batgirl
                              Danger Girl
                              Wonder Woman
                              Luke Cage
                              The Punisher
                              Ant Man
                              Dead Girl
                              Aquaman
                              SCUD
                              Spider Woman
                              Blackbolt
                              Martian Manhunter
                              

      命令行:

      grep -i man heroes.txt
                              

      將生成:

      Catwoman
                              Batman
                              Spider Man
                              Wonder Woman
                              Ant Man
                              Aquaman
                              Martian Manhunter
                              

      其中 grep 掃描 heroes.txt 文件中的每一行并查找字母 m,后面緊跟 a,然后緊跟 n。除了必須保證相鄰,這些字母可以出現(xiàn)在行的任何位置,甚至可以位于較大的單詞中間。在不考慮大小寫的情況下(-i 選項),Catwoman、Batman、Spider Man、Wonder Woman、Ant Man、Aquaman 和 Martian Manhunter 都包含字符串 man。

      grep 實用工具包含其他可優(yōu)化搜索的內(nèi)置選項。例如,-w 選項限制于匹配整個單詞,因此 grep -i -w man排除 Catwoman 和 Batman(舉例來說)。

      該工具還有一個優(yōu)秀的功能,可以排除而不是包括所有匹配的搜索結(jié)果。使用 -v 選項來排除 匹配的行。例如:

      grep -v -i 'spider' heroes.txt
                              

      將打印除了包含字符串 spider 之外的所有行。

      Catwoman
                              Batman
                              The Tick
                              Black Cat
                              Batgirl
                              Danger Girl
                              Wonder Woman
                              Luke Cage
                              The Punisher
                              Ant Man
                              Dead Girl
                              Aquaman
                              SCUD
                              Blackbolt
                              Martian Manhunter
                              

      但是,對于以下這些情況,您該如何處理?只希望得到那些開頭為“Bat”的單詞;或者以“bat”、“Bat”、“cat”或“Cat”開頭的單詞?或者希望知道有多少漫畫復(fù)仇者的名字以“man”結(jié)束。在這些實例中,類似于上述三個示例的簡單字符串搜索將無法滿足要求,因為這些搜索不區(qū)分位置。

      位置、位置、位置和備選項

      正則表達式可以 過濾特定的位置,例如行的開始或結(jié)束,以及單詞的開始和結(jié)束。正則表達式(通常簡寫為 regex)還可以描述:備選項(您可將其稱為“this”或“that”);固定長度、可變長度或不定長度的重復(fù);范圍(例如,“a-m 之間的任意字母”);還有字符的類別或種類(“可打印字符”或“標點符號”),以及其他技術(shù)。

      表 1 顯示了一些常用的正則表達式操作符。您可以連接表 1 中顯示的元素(以及其他操作符)并加以組合使用,從而構(gòu)建(非常)復(fù)雜的正則表達式。


      表 1. 常用的正則表達式操作符
      操作符 用途
      .(句號) 匹配任意單個字符。
      ^(脫字號) 匹配出現(xiàn)在行首或字符串開始位置的空字符串。
      $(美元符號) 匹配出現(xiàn)在行末的空字符串。
      A 匹配大寫字母 A
      a 匹配小寫字母 a。
      \d 匹配任意一位數(shù)字。
      \D 匹配任意單個非數(shù)字字符。
      \w 匹配任意單個字母數(shù)字字符,同義詞是 [:alnum:]。
      [A-E] 匹配任意大寫的 A、B、C、DE
      [^A-E] 匹配 A、B、C、DE 之外的任意字符。
      X? 匹配出現(xiàn)零次或一次的大寫字母 X
      X* 匹配零個或任意個大寫 X。
      X+ 匹配一個或多個字母 X
      X{n} 精確匹配 n 個字母 X。
      X{n,m} 匹配最少 n 個并且不超過 m 個字母 X。如果省略 m,表達式將嘗試匹配最少 n 個 X
      (abc|def)+ 匹配一連串的(最少一個) abcdef;abcdef 將匹配。

      以下是一些使用 grep 作為搜索工具的正則表達式示例。許多其他 UNIX 工具,包括交互式編輯器 vi 和 Emacs、流編輯器 sedawk,以及所有現(xiàn)代編程語言都支持正則表達式。在您學(xué)會正則表達式的語法(也許相當(dāng)晦澀)之后,就可以將您的專業(yè)知識靈活運用到不同的工具、編程語言和操作系統(tǒng)。

      查找以“Bat”開頭的名稱

      要查找以“Bat”開頭的名稱,請使用:

      grep -E '^Bat'
                              

      可以使用 -E 選項來指定正則表達式。^(脫字號)字符匹配行首或字符串的開頭,這是一個出現(xiàn)在每行或每個字符串開頭字符之前的假想字符。字母 B、at 只具有字面含義并且僅匹配那些特定的字符。因此,命令 grep -E '^Bat' 將生成:

      Batman
                              Batgirl
                              

      由于許多 regex 操作符也為 Shell 所使用(其中一些具有不同的用途,另外一些則有類似的用途),因此一個好的習(xí)慣是使用單引號將命令行中的每個 regex 括起來,以保護 regex 操作符免遭 Shell 的誤解。例如,*(星號)和 $(美元符號)都是 regex 操作符,并且對于您的 Shell 具有特殊的含義。

      查找以“man”結(jié)尾的名稱

      要查找以“man”結(jié)尾的名稱,可以使用 regex man$ 來匹配序列 man,并且后面緊接與 regex 操作符 $ 匹配的行(字符串)。

      查找空行

      基于 ^$ 的作用,您可以使用 regex ^$ 來查找空行(相當(dāng)于在開始之后立即結(jié)束的行)。

      備選項或集合操作符

      要查找以“bat”、“Bat”、“cat”或“Cat”開頭的單詞,可以使用以下兩個技巧。首先是備選項,如果備選項中的任意 模式匹配,都會產(chǎn)生匹配的結(jié)果。例如,命令:

      grep -E '^(bat|Bat|cat|Cat)' heroes.txt
                              

      可實現(xiàn)這一技巧。regex 操作符 |(豎線)表示備選項,因此 this|that 匹配字符串 this 或字符串 that。因此,^(bat|Bat|cat|Cat) 表示“行首緊跟 bat、Bat、catCat之一?!碑?dāng)然,可以使用 grep -i 來簡化該 regex,這樣可以忽略大小寫,從而將命令簡化為:

      grep -i -E '^(bat|cat)' heroes.txt
                              

      匹配“bat”、“Bat”、“cat”或“Cat”的另一個方法是使用 [ ](方括號)集合 操作符。如果將一組字符放在一個集合中,則可以匹配那些字符中的任意一個。(您可以將集合 看作是字符備選項的簡寫法。)

      例如,命令行:

      grep -E '^[bcBC]at' heroes.txt
                              

      與以下命令生成的結(jié)果相同:

      grep -E '^(bat|Bat|cat|Cat)' heroes.txt
                              

      您可以再次使用 -i 將 regex 簡化為 ^[bc]at。

      而且,還可以使用 -(連字符)操作符在集合中指定包含的字符范圍。例如,用戶名通常以字母開頭。假定要在提交給您的服務(wù)器的 Web 表格中驗證這樣的用戶名,可以使用類似于 ^[A-Za-z] 的 regex。此 regex 表示“字符串的開頭后緊跟任意大寫字母 (A-Z) 或任意小寫字母 (a-z)?!表槺阏f明一下,[A-z][A-Za-z] 作用相同。

      還可以在集合中混合使用范圍和單個字符。regex [A-MXYZ] 將匹配任意大寫的 A-M、X、YZ。

      并且,如果希望反轉(zhuǎn)集合(即排除集合中的任意字符),可以使用特殊集合 [^ ] 并包含要排除的范圍或字符。以下是反轉(zhuǎn)集合的示例。要查找所有名稱中包含 at 的超級英雄,并排除 Dark Knight 和 Batman,請鍵入:

      grep -i -E '[^b]at' heroes.txt
                              

      此命令生成:

      Catwoman
                              Black Cat
                              

      由于某些集合需要經(jīng)常使用,所以設(shè)計出簡化符號以代替大量字符。例如,集合 [A-z0-9_] 十分常用,因此可以簡寫為 \w。與此類似,操作符 \W 是集合 [^A-z0-9_] 的簡寫。還可以使用符號 [:alnum:] 代替 \w,使用 [^[:alnum:]] 代替 \W。

      順便說明一下,\w(以及同義詞 [:alnum:])是特定于區(qū)域的,而 [A-z0-9_] 即表示字母 A-z、數(shù)字 0-9 和下劃線。如果要開發(fā)國際化應(yīng)用程序,請使用區(qū)域特定的格式以使代碼可以在許多區(qū)域之間移植。

      跟我一起重復(fù):重復(fù),重復(fù),重復(fù)

      到目前為止,已經(jīng)介紹了字面值、位置和兩種備選項操作符。僅使用這些內(nèi)容,就可以匹配大多數(shù)具有可預(yù)測 長度的模式?,F(xiàn)在回到用戶名,通過以下 regex 命令可以確保每個用戶名以字母開頭并緊跟恰好七個字母或數(shù)字:

      [a-z][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9]
                              

      但是這樣有點笨拙。而且,它只匹配恰好八個字符的用戶名。它不會匹配三到八個字符之間的名稱,這通常也是有效的用戶名。

      正則表達式還可以包括重復(fù)修飾符。重復(fù)修飾符可以指定數(shù)量,如沒有、一個、多個、一個或多個,零或一個、五到十個,以及恰好三個。重復(fù)修飾符必須與其他模式組合,修飾符本身沒有含義。

      例如,regex:

      ^[A-z][A-z0-9]{2,7}$
                              

      可以實現(xiàn)前面描述的用戶名過濾功能。用戶名 是以字母開頭,后面緊跟至少兩個,但不超過七個字母或數(shù)字的字符串,并且緊跟字符串結(jié)尾。

      此處的位置定位點非常重要。如果沒有兩個位置操作符,則會錯誤地接受任意長度的用戶名。為什么呢?請考慮 regex:

      ^[A-z][A-z0-9]{2,7}
                              

      此命令辨別:字符串是否以字母開頭并緊跟二到七個字母?但是它未提到終止條件。因此,字符串 samuelclemens 滿足條件,但是它的長度顯然超出了有效用戶名的范圍。與此類似,省略開始定位點 ^,或同時省略兩個定位點將分別匹配以類似 munster1313 結(jié)束或包含該字符串的字符串。如果必須匹配特定的長度,請記得在要求的模式的開頭和結(jié)尾分別加上分隔符。

      以下是其他一些示例:

      • 可以使用 {2,} 查找兩次或多次重復(fù)。regex ^G[o]{2,}gle 匹配 Google、Gooogle、Goooogle 等等。
      • 重復(fù)修飾符 ?、+* 分別查找零次或一次、一次或多次,以及零次或多次重復(fù)。(例如,您可以將 ? 看作是 {0,1} 的簡寫法。)

        regex boys? 匹配 boyboys;regex Goo?gle 匹配 GogleGoogle

        regex Goo+gle 匹配 Google、Gooogle、Goooogle 等等。

        construct Goo*gle 匹配 Gogle、GoogleGooogle 等等。

      • 可以將重復(fù)修飾符應(yīng)用到單個字符(如上所示),還可以應(yīng)用到更復(fù)雜的組合。使用 () 圓括號(就像數(shù)學(xué)中的用法)將修飾符應(yīng)用到子表達式。下面是一個示例:給定文本文件 test.txt:
        The rain in Spain falls mainly
                                    on the the plain.
                                    It was the best of of times;
                                    it was the worst of times.
                                    

        命令 grep -i -E '(\b(of|the)\W+){2,}' test.txt 將生成:

        on the the plain.
                                    It was the best of of times;
                                    

      • regex 操作符 \b 匹配單詞邊界(\W\w|\w\W)。該 regex 表示“一連串完整單詞‘the’或‘of’后面緊跟非文字字符。”您可能會提出疑問,為什么 \W+ 是必需的:\b 是位于單詞開頭或結(jié)尾的空字符串。在單詞之間必須包括這一(或這些)字符,否則該 regex 將無法找到匹配。

      捕獲需要注意的內(nèi)容

      查找文本是常見的問題,但是更常見的問題則是希望在找到文本之后將其提取出來。換句話說,您希望去粗取精。

      正則表達式通過捕獲 來提取信息。如果希望將需要的文本與其他內(nèi)容分開,請使用圓括號將模式括起來。實際上,您已經(jīng)使用圓括號收集術(shù)語;在默認情況下,圓括號自動進行捕獲。

      要查看捕獲,請切換到 Perl。(grep 實用工具不支持捕獲,因為其目標是打印包含模式的行。)

      以下命令:

      perl -n -e '/^The\s+(.*)$/ && print "$1\n"' heroes.txt
                              

      將打印:

      Tick
                              Punisher
                              

      使用命令 perl -e 可以直接從命令行運行 Perl 程序。perl -n 命令針對輸入文件的每一行運行一次程序。命令的 regex 部分,即位于斜杠之間的文本(/)表示“匹配字符串的開頭,然后字母‘T’、‘h’、‘e’后緊跟一個或多個空格字符 \s+,然后捕獲直到字符串結(jié)尾的所有字符。

      Perl 捕獲內(nèi)容被放在以 $1 開頭的特殊 Perl 變量中。Perl 程序的其余部分打印捕獲的內(nèi)容。

      每個嵌套的括號對,從左開始算起,每個左圓括號加一,放在下一個特殊的數(shù)字變量中。例如:

      perl -n -e '/^(\w)+-(\w+)$/ && print "$1 $2"'
                              

      將生成:

      Spider Man
                              Ant Man
                              Spider Woman
                              

      捕獲感興趣的文本僅僅是隔靴搔癢。如果能夠準確確定材料,就可以使用其他材料改變其外觀。類似于 vi 和 Emacs 的編輯器將模式匹配與替換組合,從而將查找和替換文本組合成一步操作。還可以使用模式、替換和 sed 從命令行更改文本。

      豐富的主題

      正則表達式非常強大;可供使用的操作符的數(shù)量龐大,種類繁多。它包含如此豐富的信息和實踐知識,我們在這里所能列舉的實屬鳳毛麟角。

      幸運的是,有以下三種優(yōu)秀的正則表達式理論來源可供使用:

      • 如果在您的系統(tǒng)上有 Perl,可以參閱 Perl Regular Expression man 頁面(鍵入 perldoc perlre)。它會提供 regex 的精彩介紹,并包含許多有用的示例。許多編程語言都已采用 Perl 兼容的正則表達式 (PCRE),因此您在此 man 頁面讀到的內(nèi)容已被直接轉(zhuǎn)換到 PHP、Python、Java? 和 Ruby 編程語言,以及許多其他最新工具。
      • Jeffrey Friedl 編著的《正則表達式》(第三版)被認為是 regex 用法方面的圣經(jīng)。該書細致、準確、清晰、務(wù)實地說明了匹配的工作方式、所有的 regex 操作符、多數(shù)優(yōu)先性(限制 +* 匹配字符的數(shù)量),以及更多內(nèi)容。此外,F(xiàn)riedl 的書還包括一些令人驚嘆的正則表達式,可以準確地匹配完全限定的電子郵件地址和其他 Request for Comments (RFC) 特定的字符串。
      • Nathan Good 編著的 Regular Expression Recipes 一書提供了針對許多常見數(shù)據(jù)處理和過濾問題的有用的解決方案。如果需要提取郵政編碼、電話號碼或引用的字符串,請嘗試 Nathan 的解決方案。

      在命令行中,可以采用許多方法使用正則表達式。幾乎每個處理文本的命令都支持某種形式的正則表達式。大多數(shù) Shell 命令語法還或多或少地擴展正則表達式以匹配文件名(盡管操作符的功能可能有所不同)。

      例如,鍵入 ls [a-c] 以查找名為 a、bc 的文件。鍵入 ls [a-c]* 以查找以 a、bc 開頭的所有文件名。此處的 * 在 Shell 中不像 grep 的解釋器那樣修飾 [a-c],* 被解釋為 .*。? 操作符在 Shell 中也可以工作,但是被解釋為 .,即匹配任意單個字符。

      查看您最喜歡的實用工具或 Shell 的文檔以確定哪些 regex 操作符受支持,以及操作符可能具有的獨特性。

      下課了!

      這堂課比往常的時間要長。但是您現(xiàn)在已了解了正則表達式的基本知識。出去放松一下。

      在您享受空閑的時候,我將開始編寫很快會流行起來的經(jīng)典歌詞“描述 99 個命令的 99 行代碼”。

      共享本文……

      digg 請 Digg 這個故事
      del. 發(fā)布到 del.
      Slashdot Slashdot 一下!



      參考資料

      學(xué)習(xí)

      獲得產(chǎn)品和技術(shù)
      • IBM 試用軟件:從 developerWorks 可直接下載這些試用軟件,您可以利用它們開發(fā)您的下一個項目。


      討論


      關(guān)于作者

       

      Martin Streicher 是 Linux Magazine 的主編。他從普度大學(xué)獲得了計算機科學(xué)碩士學(xué)位,從 1982 年開始用 Pascal、C、Perl、Java 和(最近)Ruby 編程語言編寫類 UNIX 的系統(tǒng)。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多