天天看點

sed 和正規表達式

如果是用sed來取IP位址的話,我的個人習慣會寫成這樣。

複制内容到剪貼闆

代碼:

ifconfig eth0|sed -rn '/Mask/s/[^:]+:([^ ]+).*/\1/p'

簡單解釋一下這條sed

1、參數rn

r是為了讓sed支援擴充正則也就是ERE(還有BRE、PRE這些不同的流派對于正則裡元字元的表達方式都有不同,樓主可以自己Google就不在這裡解釋了),這樣可以省去後邊正則中的N多轉義符号,比如說不加r的時候()必須要寫成\(\)。

n是不要自動列印空間模式,加上他就隻列印比對的行才會去執行p的列印動作了。

2、/Mask/

找ifconfig後比對Mask這個字元串的行,這個純屬找規律。為什麼不寫inet,因為某些系統可能沒有關閉ipv6,如果以inet為過濾條件的話,那可能結果就不是一行而是兩行了。

3、s///p

這是标準的sed替換列印模式,這個應該是最基本的入門知識了。實際的意思就是“替換/源/目标/然後列印結果”

4、正則部分

為了友善解釋,我把ip位址那一行先全部寫出來 複制内容到剪貼闆

代碼:

  inet addr:192.168.5.182  Bcast:192.168.5.255  Mask:255.255.255.0

4.1對應這一整行字元串,正則的第一部分是要去掉從開頭一直到addr:

    [^:]+在正則中[]是個字元串的集合,在[]中的^是非,^:就是非冒号的字元,緊跟後邊的+代表1個或N多個整數字元,套到上邊那行,來了解就不難了。先開始是空格,然後是i然後是n然後e一直比對到r這些字元統統都不是:是以這第一部分正則時間代表的是“從行首開始N個空格然後是inet addr”

    4.2後邊緊跟着一個:,這個冒号就是比對addr和192之間的那個冒号沒什麼可解釋的。

    4.3緊接着就應該取IP位址了

    ([^ ]+)剛剛講過[^]非x字元,這裡跟剛才還是一樣的,非空格加+其實就是比對到了5.182的最後一個2,因為2之後就是空格了,不在這個正則比對範圍之内了。加個()是為了sed後邊的\1,剛剛上邊講的“/源/目标/”這種模式中,源可以寫成多個()表示的集合,第一個集合在目标中就用\1表示,第二個就是\2其他依次類推。

    4.4最後的.*是從182之後的第一個空格一直到行尾的255.0的那個0

總結一下,最開始的[^:]+:比對了IP位址之前的所有字元,後邊的.*比對了IP位址之後的所有字元,而中間括号裡的[^ ]+正好比對了所有IP位址字元,再配合上後邊的\1,就實作了僅僅取得IP位址的目的。 複制内容到剪貼闆

代碼:

[[email protected] data]# ifconfig eth0 eth0      Link encap:Ethernet  HWaddr 00:22:19:D5:58:B3             inet addr:192.168.5.182  Bcast:192.168.5.255  Mask:255.255.255.0           inet6 addr: fe80::222:19ff:fed5:58b3/64 Scope:Link           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1           RX packets:982911834 errors:0 dropped:22 overruns:0 frame:0           TX packets:1186926645 errors:0 dropped:0 overruns:0 carrier:0           collisions:0 txqueuelen:1000            RX bytes:961744663911 (895.6 GiB)  TX bytes:1347402596792 (1.2 TiB)           Interrupt:169 Memory:dfdf0000-dfe00000  [root@182 data]# ifconfig eth0|sed -rn '/Mask/s/[^:]+:([^ ]+).*/\1/p' 192.168.5.182

sed是一個非互動性性文本編輯器, 它編輯檔案或标準輸入導出的檔案拷貝。标準輸入可能是來自鍵盤、檔案重定向、字元串或變量,或者是一個管道檔案。sed可以随意編輯小或大的檔案,有許多 sed指令用來編輯、删除,并允許做這項工作時不在現場。sed一次性處理所有改變,因而變得很有效,對使用者來說,最重要的是節省了時間。sed必須通過行号和正規表達式指定要改變的文本行

sed怎樣讀取資料:

    sed從檔案的一個文本行或從标準輸入的幾種格式中讀取資料,将之拷貝到一個編輯緩沖區,然後讀指令行或腳本的第一條指令,并使用這些指令查找模式或定位行号編輯它,重複過程直到指令結束

sed指令的調用:

    在指令行鍵入指令;将sed指令插入腳本檔案,然後調用sed;将sed指令插入腳本檔案,并使sed腳本可執行

    sed [option] sed指令 輸入檔案            在指令行使用sed指令,實際指令要加單引号

    sed [option] -f sed腳本檔案 輸入檔案     使用sed腳本檔案

    sed腳本檔案 [option] 輸入檔案            第一行具有sed指令解釋器的sed腳本檔案

    option如下: 

      n 不列印; sed不寫編輯行到标準輸出,預設為列印所有行(編輯和未編輯),p指令可以用來列印編輯行

      c 下一指令是編輯指令,使用多項編輯時加入此選項

      f 如果正在調用sed腳本檔案,使用此選項,此選項通知sed一個腳本檔案支援所用的sed指令,如

          sed -f myscript.sed input_file  這裡myscript.sed即為支援sed指令的檔案

    使用重定向檔案即可儲存sed的輸出

使用sed在文本中定位文本的方式:

    x       x為一行号,比如1

    x,y     表示行号範圍從x到y,如2,5表示從第2行到第5行

    /pattern/    查詢包含模式的行,如/disk/或/[a-z]/

    /pattern/pattern/   查詢包含兩個模式的行,如/disk/disks/

    /pattern/,x  在給定行号上查詢包含模式的行,如/disk/,3

    x,/pattern/  通過行号和模式查詢比對行,如 3,/disk/

    x,y!    查詢不包含指定行号x和y的行

基本sed編輯指令:

    p      列印比對行                      c/    用新文本替換定位文本

    =      顯示檔案行号                    s     使用替換模式替換相應模式

    a/     在定位行号後附加新文本資訊        r     從另一個文本中讀文本

    i/     在定位行号後插入新文本資訊        w     寫文本到一個檔案

    d      删除定位行                      q     第一個模式比對完成後退出或立即退出

    l      顯示與八進制ASCII代碼等價的控制字元        y  傳送字元

    n      從另一個文本中讀文本下一行,并附加在下一行   {}     在定位行執行的指令組

    g      将模式2粘貼到/pattern n/

基本sed程式設計舉例:

    使用p(rint)顯示行: sed -n '2p' temp.txt   隻顯示第2行,使用選項n

    列印範圍:  sed -n '1,3p' temp.txt         列印第1行到第3行

    列印模式:  sed -n '/movie/'p temp.txt     列印含movie的行

    使用模式和行号查詢:  sed -n '3,/movie/'p temp.txt   隻在第3行查找movie并列印

    顯示整個檔案:  sed -n '1,$'p temp.txt      $為最後一行

    任意字元:  sed -n '/.*ing/'p temp.txt     注意是.*ing,而不是*ing

    列印行号:  sed -e '/music/=' temp.txt

    附加文本:(建立sed腳本檔案)chmod u+x script.sed,運作時./script.sed temp.txt

        #!/bin/sed -f

        /name1/ a/             #a/表示此處換行添加文本

        HERE ADD NEW LINE.     #添加的文本内容

    插入文本: /name1/ a/ 改成 4 i/ 4表示行号,i插入

    修改文本: /name1/ a/ 改成 /name1/ c/ 将修改整行,c修改

    删除文本: sed '1d' temp.txt  或者 sed '1,4d' temp.txt

    替換文本: sed 's/source/OKSTR/' temp.txt     将source替換成OKSTR

             sed 's//$//g' temp.txt             将文本中所有的$符号全部删除

             sed 's/source/OKSTR/w temp2.txt' temp.txt 将替換後的記錄寫入檔案temp2.txt

    替換修改字元串: sed 's/source/"ADD BEFORE" &/p' temp.txt

             結果将在source字元串前面加上"ADD BEFORE",這裡的&表示找到的source字元并儲存

    sed結果寫入到檔案: sed '1,2 w temp2.txt' temp.txt

                     sed '/name/ w temp2.txt' temp.txt

    從檔案中讀文本: sed '/name/r temp2.txt' temp.txt

    在每列最後加文本: sed 's/[0-9]*/& Pass/g' temp.txt

    從shell向sed傳值: echo $NAME | sed "s/go/$REP/g"   注意需要使用雙引号

快速一行指令:

    's//.$//g'         删除以句點結尾行

    '-e /abcd/d'       删除包含abcd的行

    's/[][][]*/[]/g'   删除一個以上空格,用一個空格代替

    's/^[][]*//g'      删除行首空格

    's//.[][]*/[]/g'   删除句号後跟兩個或更多的空格,用一個空格代替

    '/^$/d'            删除空行

    's/^.//g'          删除第一個字元,差別  's//.//g'删除所有的句點

    's/COL/(.../)//g'  删除緊跟COL的後三個字母

    's/^g'         删除路徑中第一個/

///

、使用句點比對單字元    句點“.”可以比對任意單字元。“.”可以比對字元串頭,也可以是中間任意字元。假定正在過濾一個文本檔案,對于一個有1 0個字元的腳本集,要求前4個字元之後為X C,比對操作如下:. . . .X C. . . .

2、在行首以^比對字元串或字元序列    ^隻允許在一行的開始比對字元或單詞。在行首第4個字元為1,比對操作表示為:^ . . . 1

3、在行尾以$比對字元串或字元    可以說$與^正相反,它在行尾比對字元串或字元, $符号放在比對單詞後。如果在行尾比對單詞j e t 0 1,操作如下:j e t 0 1 $    如果隻傳回包含一個字元的行,操作如下:^ . $

4、使用*比對字元串中的單字元或其重複序列    使用此特殊字元比對任意字元或字元串的重複多次表達式。

5、使用/屏蔽一個特殊字元的含義    有時需要查找一些字元或字元串,而它們包含了系統指定為特殊字元的一個字元。如果要在正規表達式中比對以* . p a s結尾的所有檔案,可做如下操作:/ * / . p a s

6、使用[]比對一個範圍或集合     使用[ ]比對特定字元串或字元串集,可以用逗号将括弧内要比對的不同字元串分開,但并不強制要求這樣做(一些系統提倡在複雜的表達式中使用逗号),這樣做可以增 加模式的可讀性。使用“ -”表示一個字元串範圍,表明字元串範圍從“ -”左邊字元開始,到“ -”右邊字元結束。假定要比對任意一個數字,可以使用:[ 0 1 2 3 4 5 6 7 8 9 ]    要比對任意字母,則使用:[ A - Z a - z ]表明從A - Z、a - z的字母範圍。

7、使用/{/}比對模式結果出現的次數    使用*可比對所有比對結果任意次,但如果隻要指定次數,就應使用/ { / },此模式有三種形式,即:

    pattern/{n/} 比對模式出現n次。

    pattern/{n,/} 比對模式出現最少n次。

    pattern/{n,m} 比對模式出現n到m次之間,n , m為0 - 2 5 5中任意整數。

    比對字母A出現兩次,并以B結尾,操作如下:A / { 2 / } B比對值為A A B    比對A至少4次,使用:A / { 4 , / } B

    在s h e l l程式設計中,一段好的腳本與完美的腳本間的差别之一,就是要熟知正規表達式并學會使用它們。相比較起來,用一個指令抽取一段文本比用三四個指令得出同樣的結果要節省許多時間。

//

正規表達式使用詳解(一) 

2000-04-26呂曉波 

  如果我們問那些UNIX系統的愛好者他們最喜歡什麼,答案除了穩定 的系統和可以遠端啟動之外,十有八九的人會提到正規表達式;如果我們再問他們最頭痛的是什麼,可能除了複雜的程序控制和安裝過程之外,還會是正規表達式。 那麼正規表達式到底是什麼?如何才能真正的掌握正規表達式并正确的加以靈活運用?本文将就此展開介紹,希望能夠對那些渴望了解和掌握正規表達式的讀者有所 助益。 

入門簡介 

  簡單的說,正規表達式是一種可以用于模式比對和替換的強有力的工具。我們可以在幾乎所 有的基于UNIX系統的工具中找到正規表達式的身影,例如,vi編輯器,Perl或PHP腳本語言,以及awk或sed shell程式等。此外,象JavaScript這種用戶端的腳本語言也提供了對正規表達式的支援。由此可見,正規表達式已經超出了某種語言或某個系統的 局限,成為人們廣為接受的概念和功能。 

  正規表達式可以讓使用者通過使用一系列的特殊字元建構比對模式,然後把比對模式與資料檔案、程式輸入以及WEB頁面的表單輸入等目标對象進行比較,根據比較對象中是否包含比對模式,執行相應的程式。 

   舉例來說,正規表達式的一個最為普遍的應用就是用于驗證使用者線上輸入的郵件位址的格式是否正确。如果通過正規表達式驗證使用者郵件位址的格式正确,使用者所 填寫的表單資訊将會被正常處理;反之,如果使用者輸入的郵件位址與正則表達的模式不比對,将會彈出提示資訊,要求使用者重新輸入正确的郵件位址。由此可見正則 表達式在WEB應用的邏輯判斷中具有舉足輕重的作用。 

基本文法 

  在對正規表達式的功能和作用有了初步的了解之後,我們就來具體看一下正規表達式的文法格式。 

  正規表達式的形式一般如下: 

  /love/ 

   其中位于“/”定界符之間的部分就是将要在目标對象中進行比對的模式。使用者隻要把希望查找比對對象的模式内容放入“/”定界符之間即可。為了能夠使使用者 更加靈活的定制模式内容,正規表達式提供了專門的“元字元”。所謂元字元就是指那些在正規表達式中具有特殊意義的專用字元,可以用來規定其前導字元(即位 于元字元前面的字元)在目标對象中的出現模式。 

  較為常用的元字元包括: “+”, “*”,以及 “?”。其中,“+”元字元規定其前導字元必須在目标對象中連續出現一次或多次,“*”元字元規定其前導字元必須在目标對象中出現零次或連續多次,而“?”元字元規定其前導對象必須在目标對象中連續出現零次或一次。 

  下面,就讓我們來看一下正規表達式元字元的具體應用。 

  /fo+/ 

  因為上述正規表達式中包含“+”元字元,表示可以與目标對象中的 “fool”, “fo”, 或者 “football”等在字母f後面連續出現一個或多個字母o的字元串相比對。 

  /eg*/ 

  因為上述正規表達式中包含“*”元字元,表示可以與目标對象中的 “easy”, “ego”, 或者 “egg”等在字母e後面連續出現零個或多個字母g的字元串相比對。 

  /Wil?/ 

  因為上述正規表達式中包含“?”元字元,表示可以與目标對象中的 “Win”, 或者 “Wilson”,等在字母i後面連續出現零個或一個字母l的字元串相比對。 

  除了元字元之外,使用者還可以精确指定模式在比對對象中出現的頻率。例如, 

  /jim{2,6}/ 

  上述正規表達式規定字元m可以在比對對象中連續出現2-6次,是以,上述正規表達式可以同jimmy或jimmmmmy等字元串相比對。 

  在對如何使用正規表達式有了初步了解之後,我們來看一下其它幾個重要的元字元的使用方式。 

  /s:用于比對單個空格符,包括tab鍵和換行符; 

  /S:用于比對除單個空格符之外的所有字元; 

  /d:用于比對從0到9的數字; 

  /w:用于比對字母,數字或下劃線字元; 

  /W:用于比對所有與/w不比對的字元; 

  . :用于比對除換行符之外的所有字元。 

  (說明:我們可以把/s和/S以及/w和/W看作互為逆運算) 

  下面,我們就通過執行個體看一下如何在正規表達式中使用上述元字元。 

  //s+/ 

  上述正規表達式可以用于比對目标對象中的一個或多個空格字元。 

  //d000/ 

  如果我們手中有一份複雜的财務報表,那麼我們可以通過上述正規表達式輕而易舉的查找到所有總額達千元的款項。 

  除了我們以上所介紹的元字元之外,正規表達式中還具有另外一種較為獨特的專用字元,即定位符。定位符用于規定比對模式在目标對象中的出現位置。 

   較為常用的定位符包括: “^”, “$”, “/b” 以及 “/B”。其中,“^”定位符規定比對模式必須出現在目标字元串的開頭,“$”定位符規定比對模式必須出現在目标對象的結尾,/b定位符規定比對模式必須 出現在目标字元串的開頭或結尾的兩個邊界之一,而“/B”定位符則規定比對對象必須位于目标字元串的開頭和結尾兩個邊界之内,即比對對象既不能作為目标字 符串的開頭,也不能作為目标字元串的結尾。同樣,我們也可以把“^”和“$”以及“/b”和“/B”看作是互為逆運算的兩組定位符。舉例來說: 

  /^hell/ 

  因為上述正規表達式中包含“^”定位符,是以可以與目标對象中以 “hell”, “hello”或 “hellhound”開頭的字元串相比對。 

  /ar$/ 

  因為上述正規表達式中包含“$”定位符,是以可以與目标對象中以 “car”, “bar”或 “ar” 結尾的字元串相比對。 

  //bbom/ 

  因為上述正規表達式模式以“/b”定位符開頭,是以可以與目标對象中以 “bomb”, 或 “bom”開頭的字元串相比對。 

  /man/b/ 

  因為上述正規表達式模式以“/b”定位符結尾,是以可以與目标對象中以 “human”, “woman”或 “man”結尾的字元串相比對。 

  為了能夠友善使用者更加靈活的設定比對模式,正規表達式允許使用者在比對模式中指定某一個範圍而不局限于具體的字元。例如: 

  /[A-Z]/ 

  上述正規表達式将會與從A到Z範圍内任何一個大寫字母相比對。 

  /[a-z]/ 

  上述正規表達式将會與從a到z範圍内任何一個小寫字母相比對。 

  /[0-9]/ 

  上述正規表達式将會與從0到9範圍内任何一個數字相比對。 

  /([a-z][A-Z][0-9])+/ 

   上述正規表達式将會與任何由字母和數字組成的字元串,如 “aB0” 等相比對。這裡需要提醒使用者注意的一點就是可以在正規表達式中使用 “()” 把字元串組合在一起。“()”符号包含的内容必須同時出現在目标對象中。是以,上述正規表達式将無法與諸如 “abc”等的字元串比對,因為“abc”中的最後一個字元為字母而非數字。 

  如果我們希望在正規表達式中實作類似程式設計邏輯中的“或”運算,在多個不同的模式中任選一個進行比對的話,可以使用管道符 “|”。例如: 

  /to|too|2/ 

  上述正規表達式将會與目标對象中的 “to”, “too”, 或 “2” 相比對。 

  正規表達式中還有一個較為常用的運算符,即否定符 “[^]”。與我們前文所介紹的定位符 “^” 不同,否定符 “[^]”規定目标對象中不能存在模式中所規定的字元串。例如: 

  /[^A-C]/ 

  上述字元串将會與目标對象中除A,B,和C之外的任何字元相比對。一般來說,當“^”出現在 “[]”内時就被視做否定運算符;而當“^”位于“[]”之外,或沒有“[]”時,則應當被視做定位符。 

  最後,當使用者需要在正規表達式的模式中加入元字元,并查找其比對對象時,可以使用轉義符“/”。例如: 

  /Th/*/ 

  上述正規表達式将會與目标對象中的“Th*”而非“The”等相比對。

繼續閱讀