瞭解正則表達式語法:git
正則表達式(regular expression)描述了一種字符串匹配的模式,能夠用來檢查一個串是否含有某種子串、將匹配的子串作替換或者從某個串中取出符合某個條件的子串等。正則表達式
\列出目錄時,dir *.txt 或 ls *.txt 中的 *.txt 就不是一個正則表達式,由於這裏 * 與正則式的 * 的含義是不一樣的。express
\構造正則表達式的方法和建立數學表達式的方法同樣。也就是用多種元字符與運算符能夠將小的表達式結合在一塊兒來建立更大的表達式。正則表達式的組件能夠是單個的字符、字符集合、字符範圍、字符間的選擇或者全部這些組件的任意組合。ide
正則表達式是由普通字符(例如字符 a 到 z)以及特殊字符(稱爲"元字符")組成的文字模式。模式描述在搜索文本時要匹配的一個或多個字符串。正則表達式做爲一個模板,將某個字符模式與所搜索的字符串進行匹配。測試
普通字符字體
普通字符包括沒有顯式指定爲元字符的全部可打印和不可打印字符。這包括全部大寫和小寫字母、全部數字、全部標點符號和一些其餘符號。編碼
元字符彙總spa
. 匹配除換行符之外的任意單個字符。在awk中,句點也能匹配換行符。code
* 匹配任意一個(包括零個)在它面前的字符,(包括由正則表達式指定的字符)orm
[...]匹配方括號中的字符類的任意一個。若是方括號中第一個字符爲脫節字符(^),則表示否認匹配,即匹配除了換行符和類中列出的那些字符之外的全部字符,在awk中也匹配換行符。連字符(-)用於表示字符的範圍。若是類中的第一個字符爲右方括號(]),則表示它是類的成員。全部其餘的元字符在被指定爲類中的成員時都會失去他們原來的意義。
^ 若是做爲正則表達式中的第一個字符,則表示匹配行的開始。在awk中匹配字符串的開始,即便字符串包含嵌入的換行符。
$ 若是做爲正則表達式中的最後一個字符,則表示匹配行的結束。在awk中匹配字符串的結尾,即便字符串包含嵌入的換行符。
\{n,m\}匹配它前面某個範圍內單個字符出現的次數(包括由正則表達式指定的字符),\{n\}將匹配n次出現,\{n,\}至少匹配n次出現,並且\{n,m\}匹配n和m之間的任意次出現。
\ 轉義隨後的特殊字符
擴展的元字符(egrep和awk)
+匹配前面的正則表達式的一次或者屢次出現。
?匹配前面的正則表達式的零次或者一次出現。
|指定能夠匹配其前面的或者後面的的正則表達式。
()對正則表達式分組。
{n,m}匹配它前面某個範圍內單個字符出現的次數,(包括由正則表達式指定的字符),{n}表示匹配n次出現,{n, }至少匹配n次出現,{n,m}匹配n和m之間的任意次出現。(用於POSIX的egrep和POSIX的awk,而不是傳統的egrep和awk)。
普通存在的反斜槓 \
元字符反斜槓(\)將元字符轉換爲普通字符(和將普通字符轉換爲元字符),它強制將任意元字符解釋爲普通文字,以便匹配該字符自己。
它的用法:\( \) \{ \} \n
字符類中的特殊字符
\ 轉義任意特殊字符(只用於awk中) 只在awk中式特殊的,所以可使用字符類"[a\]1]"以匹配一個a、一個],或一個1。
-當它不在第一個或者最後一個位置時,表示一個範圍
^僅當在第一個位置時表示翻轉匹配
字符的範圍
連字符用於指定一個字符範圍,例如,全部大寫字母的範圍能夠指定爲:[A-Z]
一個數字的數字範圍能夠指定爲:[0-9]
該字符類有助於解決匹配文章引用的問題。
例如:[cC]hapter [1-9]
它匹配字符串‘chapter’或者‘Chapter’且後面跟有空格,而後是從1到9的任意單個數字。
eg: you will find the information in chapter 9.
[0-9a-z?,.;:'"]這個表達式將匹配任意的單個字符,能夠是數字,小寫字母,問號,逗號,句點,分號,冒號,單引號,引號。記住每一個字符類都匹配單個字符。
若是指定多個類,能夠描述多個連續的字符。
[a-zA-Z][.?!]這個表達式匹配「任意後面跟有句點,問號,感嘆號的小寫或者大寫的字面」
[-+*/]若是連字符在一個類中是第一個或者最後一個字符,則失去其特殊含義,爲了匹配算是操做符,在下面的示例中將連字符(-)放在第一位。
用正在匹配日期的兩種格式:
MM-DD-YY
MM/DD/YY
排除字符集
一般字符類包括在哪一個位置想要匹配的全部字符。在類中做爲第一個字符的脫字節(^)將類中的全部字符由排除再被匹配以外。相反,除換行符之外的的沒有列在方括號中的任意字符都將匹配。
[^0-9] 將匹配任意非數字字符。它將匹配全部的大寫和小寫字母,以及全部特殊符號,例如,標點符號。
[^aeiou]排除元音,匹配任意的輔音,大寫的任意元音,任意標點符號或者特殊字符。
舉例以下的表達式:
\.DS "[^1]" 該表達式匹配字符串,「.DS」其後依次跟隨一個空格、一個雙引號、一個非數字和一個雙引號。這樣設置是爲了不匹配以下:.DS "1" ,而匹配這樣的行: .DS "|" .DS "2"
POSIX字符類
類 匹配字符
[:alnum:] 可打印的字符(包括空白字符)
[:alpha:] 字母字符
[:blank:] 空格和製表符
[:cntrl:] 控制字符
[:digit:] 數字字符
[:graph:] 可打印的和可見的(非空格)字符
[:lower:] 小寫字符
[:print:] 可打印的字符(包括空白字符)
[:punct:] 標點符號字符
[:space:] 空白字符
[:upper:] 大寫字符
[:xdigit:] 十六進制數字
重複出現的字符
星號(*)元字符表示它前面的正則表達式能夠出現零次或屢次。也就是說,若是它修改了單個字符,那麼該字符能夠在那裏也能夠不在那裏,而且若是它在那裏,那可能會不止出現一個。可使用星號元字符匹配出如今引號中的單詞。
當星號用於修復字符類時,則能夠匹配類中的任意數目的的字符。
cat summ.txt
i can do it
i cannot do it
i can not do it
i can't do it
i cant do it
##############################
匹配以上語句的否認語句,可是不匹配確定語句,可使用以下的正則
grep "can[ no' ]*t" summ.txt
i cannot do it
i can not do it
i can't do it
i cant do it
元字符加號能夠被認爲是「至少一個」的前導字符,事實上,他和許多人使用的「*」號相對應。
問號(?)匹配零次或者一次出現。例如:
「80286」「80386」「80486」「80586」使用正則表達式匹配,若是咱們還想匹配字符串「8086」,可使用egrep或awk編寫正則表達式。
80[2345]?86 :它匹配"80"後面跟的"一個2","一個3","一個4","一個5",或者沒有字符,而後跟字符串「86」。
匹配單詞,有時候匹配單詞很難,例如:想匹配模式「book」,搜索會命中包含單詞「book」「books」「bookish」"handbook"「booky」,若是遇到此類狀況,則須要在"book"先後使用空格來限制匹配狀況。
舉例:
[root@localhost opt]# cat zhang.txt
Here are the books that you requested
Yes,it is a good book for children
it is amazing to think that it was called a "harmful book" when once you get to the end of the book,you can't believe
. book.(.爲空格的意思)
[root@localhost opt]# grep ' book ' zhang.txt
Yes,it is a good book for children
可是此表達式只匹配單詞「book」,它會丟掉匹配「books」,爲了匹配單數或者複數單詞,可能要使用星號元字符。
[root@localhost opt]# grep ' books* ' zhang.txt
Here are the books that you requested
Yes,it is a good book for children
. books.*這樣能夠匹配「book」或者「books」然而,若是單詞後面有逗號,句點,問號或者引號時就不匹配「book」。
[root@localhost opt]# grep ' book.* ' zhang.txt
Here are the books that you requested
Yes,it is a good book for children
it is amazing to think that it was called a "harmful book" when once you get to the end of the book,you can't believe
當星號和通配符(.)結合起來使用時,能夠匹配任意字符的零次或者屢次出現。
. book.* .這個表達式匹配字符串「book」,其後面跟有任意個字符或者沒有字符,最後跟着空格。
. book.? .
定位元字符
有兩個元字符用於指定字符串出如今行首或者行末的上下文。脫字符(^)元字符是指示開始的單字符正則表達式,美圓符號($)元字符是指示行結尾的單字符正則表達式。這些一般被稱爲「定位符」,由於他們將匹配限定在特定的位置。
[root@localhost opt]# cat zhang.txt
Here are the books that you requested
Yes,it is a good book for children
it is amazing to think that it was called a "harmful book" when once you get to the end of the book,you can't believe
可使用如下的表達式打印以製表符開始的行:
^.
eg:
[root@localhost opt]# grep -c '^.' zhang.txt
3
一般,使用vi輸入要由troff處理的文本,而且不想讓空格出如今行的結尾。若是想找到(而且刪除他們),下面的正則表達式能夠匹配在結尾處有一個或者多個的行。
()()*$[()表示的是空格]
[root@localhost opt]# grep -c ' *$' zhang.txt
0
匹配行首有一個句點,隨後跟有兩個字符的字符串,而後是一個空格的行。 ^\...()[()表示的是空格]
可使用兩個連續的定位元字符來匹配空行,例如:
[root@localhost opt]# grep -c '^$' zhang.txt
2
可使用sed來刪除空行,下面的正則表達式可用於匹配空行,即便其中包含空格:'^ *$'。 一樣可以使用此表達式匹配整個行: '^.*$'
[root@localhost opt]# grep -c '^ *$' zhang.txt
2
[root@localhost opt]# grep -c '^.*$' zhang.txt
5
字符的跨度
這個元字符指示了一個不肯定的長度,這容許你指定重複出現的字符,如今咱們來看一對用於指定跨度並決定跨度長度的元字符,能夠指定一個字母字符或正則表達式出現的最小或者最大的次數。
在grep和sed中使用\{和\},POSIX egrep和 POSIX awk 使用{和}。在任意狀況下大括號包圍一個或者兩個參數。
\{n,m\} :n和m是0到255之間的整數,若是隻指定\{n\}自己,那麼將精確匹配前面的字符或者或正則表達式的n次出現。若是指定\{n,m\},那麼就匹配出現的次數爲n和m之間的任意數。
注意:「?」等價於"\{0,1\}","*"等價於"\{0,\}" , "+"等價於"\{1,\}",沒有等價於"\{1\}"的修飾符。
例如:下面的表達式將匹配「1001」、「10001」、「100001」可是不匹配「101」或者「1000001」
10\{2,4\}1
[0-9]\{3\}-[0-9]\{2\}-[0-9]\{4\} 3個數字,一個連字符,加兩個數字一個連字符,四個數字
[0-9]\{3\}-[0-9]\{4\}三個數字,一個連字符,四個數字
若是使用POSIX以前的awk,大括號就不用寫,只能簡單的重複適當次數的字符類。
[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]
選擇性操做
豎線(|)元字符是元字符擴展集的一部分,用於指定正則表達式的聯合,若是某行匹配其中的一個正則表達式,那麼它就匹配該模式。
例如:LINUX|UNIX將匹配包含字符串「Linux」或者「Unix」的行。也能夠指定更多的選擇,
LINUX|UNIX|EATANB 表示:使用egrep打印匹配這3種模式的任意一種的行。
sed中沒有聯合元字符,能夠分別指定每種模式。
分組操做
園括號()用於對正則表達式進行分組並設置優先級,他們是元字符擴展集的一部分,假設在文本文件中將公司的名稱爲:「BigOne」或者是「BigOne Computer」,使用以下的正則表達式:
BigOne ( Computer)? #將匹配字符串"BigOne"自己或者後面跟有一個字符串「 Computer」的形式。一樣,有些術語有時會有全拼,有時會用縮寫,則可使用以下:
[root@localhost opt]# egrep "Labo(ratorie)?s" mail.list
Bell Laboratories,Lucent Technologies
Bell Labos
可使用豎線和圓括號來對選擇性操做進行分組,能夠用來指定單複數的匹配例如:
compan(y|ies)
注意:在大多數的sed和grep版本中,不能對加圓括號的一組字符應用數量詞。可是在awk和egrep的全部版本中,都是能夠的。
測試:使用前文討論過的新的元字符來從新構建搜索單個單詞的正則表達式。>想打印,<表示不想打印
[root@localhost opt]# cat book.list
>This file tests for book in various places, such as
>book at the beginning of a line or
>at the end of a line book,
>as well as the plural books and
<handbooks.Here are some
<phrases that use the word in different ways:
>"book of the year award"
>to look for a line with the word "book"
>A GREAT book!
>A great book? No.
>told them about (the books) until it
>Here are thr books that you requested
>Yes,it is a good book for children
>amazing that it was called a "harmful book" when
>once you get to the end of the book, you can't believe
<A well-written regular expression should
<avoid mathing unrelated words,
<such as booky(is that a word?)
<and bookish and
<bookworm and so on.
################################################
[root@localhost opt]# grep ' book.* ' book.list
>This file tests for book in various places, such as
>as well as the plural books and
>A great book? No.
>told them about (the books) until it
>Here are thr books that you requested
>Yes,it is a good book for children
>amazing that it was called a "harmful book" when
>once you get to the end of the book, you can't believe
<such as booky(is that a word?)
<and bookish and
它只是打印咱們想要匹配行的13行中的8行,並打印咱們不想匹配行中的2行,這個表達式匹配包含單詞「booky」和「bookish」的行,他忽略了行開始或者結束出的「book」,當涉及某種標點符號時它忽略「book」。
爲了進一步限制搜索,咱們必須使用字符類,通常地,能夠結束單詞的字符列表是標點符號。例如;
? . , ! ; : '
另外,引號,圓括號,大括號和方括號能夠包圍一個單詞出如今單詞的左側或者右側:
" () {} []
你還必須調整單詞的複數或者是全部格形式。
所以,應該有兩個不一樣的字符類,單詞以前和單詞以後。記住咱們必須作的就是列出方括號中的類的成員,在單詞前面使用:
["[{(]
在單詞後面使用:
[]})"?!.,;:' s ]
注意:在類中第一個位置放置閉方括號,表示它是類的成員而不是閉方括號。將以上的類放置在一塊兒,獲得以下的正則表達式:
["[{(]*book[]})"?!.,;:' s]*
[root@localhost opt]# grep " [\"[{(]*book[]})\"?\!\.\,;\:' s]* " book.list
>This file tests for book in various places, such as
>as well as the plural books and
>A great book? No.
>told them about (the books) until it
>Here are thr books that you requested
>Yes,it is a good book for children
>amazing that it was called a "harmful book" when
>once you get to the end of the book, you can't believe
咱們排除了咱們不想要的行,可是都是由在行的開始或結尾處出現的字符串所致使的錯誤。由於在行的開始處或者結尾處沒有空格。因此模式不被匹配,可使用定位元字符^和$。由於要匹配一個空格或行的開始或者結尾,可使用egrep並指定的「或」元字符,同時用圓括號分隔。例如:爲了匹配行的開始或者一個空格,能夠編寫下面的表達式:
(^| )由於|和()是元字符擴展集的一部分,因此若是使用的是sed,則必須編寫不一樣的表達式來處理每一種狀況。
所以表達式以下:
[root@localhost opt]# egrep "(^|)[\"[{(]*book[]})\"?\!\.\,;\:' s]*( |$)" book.list
>This file tests for book in various places, such as
>book at the beginning of a line or
>at the end of a line book,
>as well as the plural books and
>"book of the year award"
>to look for a line with the word "book"
>A GREAT book!
>A great book? No.
>told them about (the books) until it
>Here are thr books that you requested
>Yes,it is a good book for children
>amazing that it was called a "harmful book" when
>once you get to the end of the book, you can't believe
匹配的範圍
A*Z這個表達式匹配「零次或者屢次出現的A,同時A後面跟字符串Z」。它產生的結果與僅僅指「Z」是相同的。字符A能夠在那裏也能夠不在那裏,事實上,字符Z是惟一匹配的字符。
例如:
[root@localhost opt]# grep 'A*Z' hello
All of us,including Zippy,our dog
some of us ,including Zippy,our dog
若是咱們想要匹配的範圍擴展到從A到Z,則須要修改正則表達式爲:A.*Z
" .* "能夠解釋爲出現零次或者屢次的任意字符,這意味着能夠找到「出現任意次的字符」,包括什麼也沒有的狀況。整個表達式表示A和Z之間有任意數目的字符,「A」是模式中的開始字符,「Z」是最後一個字符,在它們之間能夠有任意個字符或者是沒有字符。
[root@localhost opt]# grep 'A.*Z' hello 紅色字體表示匹配的範圍
All of us,including Zippy,our dog
匹配的範圍從A到Z,相同的正則表達式還匹配下面的行
[root@localhost opt]# grep 'A.*Z' hello
i heard it on radio station WVAZ ^^ 1060
字符串A.*Z匹配A後面跟有任意個字符(包括零個字符),再跟有Z的模式:
[root@localhost opt]# grep 'A.*Z' hello
All of us,including Zippy,our dog
i heard it on radio station WVAZ ^^ 1060
All of us, including Zippy and Ziggy
All of us, including Zippy and Ziggy and Zelda
注意:正則表達式A.*Z在每種狀況下都匹配可能爲最長的範圍。當咱們想要匹配最短的範圍時會出問題。
限制範圍
前面說過,正則表達式嘗試匹配最長的字符串,而且這可能會引發意想不到的問題。例如:如下的表達式
" .* "
輸入字符串以下:
[root@localhost opt]# cat list1.txt
.Se "Appendix" "Full Program Listings"
要匹配第一個參數,則正則表達式以下:
\.Se ".*"
然而,由於模式中的第二個引號與該行上的最後一個引號匹配,因此它結束匹配整個行。若是知道參數的個數,那麼能夠對每一個進行說明:
\.Se ".*" ".*"
雖然這種方法能夠像指望的那樣工做,可是每行也許不會有相同書目的參數,省略你只想要第一個參數。這裏有一個匹配兩個引號之間最短範圍的正則表達式:
"[^ "]*"
如今咱們來看看兩列數字之間使用句點字符(.)做爲引導符的幾行:
1........5
5.........10
10........20
100.........200
這裏匹配引導字符的困難是它們的數量是可變的,假如想用單個製表符取代全部的引導符,則能夠按下面的形式編寫一個匹配行的正則表達式:[0-9][0-9]*\.\.*[0-9][0-9]*
爲了限制匹配,能夠指定全部的行共用句點的最小數目:[0-9][0-9]*\.\{5,\}*[0-9][0-9]*這個表達式使用sed中可用的大括號來匹配「一個數字後面至少跟5個句點,而後再跟有一個數字的狀況」。
[root@localhost opt]# sed 's/\([0-9][0-9]*\)\.\{5,\}\([0-9][0-9]*\)/\1-\2/' list2.txt
1-5
5-10
10-20
100-200
使用喜歡的元字符
有用的正則表達式:
州的郵政編碼
(空格)[A-Z][A-Z](空格)
城市、州
^ .*,(空格)[A-Z][A-Z]
城市、州、郵編(POSIX/egrep)
^ .*,(空格)[A-Z][A-Z][0-9]{5}(-[0-9]{4})?
月、日、年
[A-Z][a-z]\{3,9\}(空格)[0-9]\{1,2\},(空格)[0-9]\{4\}
美國社會保險號
[0-9]\{3\}-[0-9]\{2\}-[0-9]\{4\}
北美地區電話
[0-9]\{3\}-[0-9]\{4\}
格式化的美圓數額
\$[(空格)0-9]*\.[0-9][0-9]
troff嵌入的字體請求
\\f[(BIRP]C*[BW]*
troff的請求
^ \.[a-z]\{2\}
troff 宏
^ \.[a-z12].
帶有參數的troff的宏
^ \.[a-z12].(空格)" .*"
HTML嵌入的代碼
<[^ >]*>
Ventura Publisher style codes
^ @.*(空格)=(空格).*
匹配空行
^$
匹配整行
^.*$
匹配一個或者多個空格
(空格)(空格)*
..........