Linux之正則表達(dá)式

正則表達(dá)式:定義的模式模板(pattern template),Linux工具可以用它來過濾文本懒构。
如果匹配了定義的模式,它就會被接受并進(jìn)一步處理耘擂;如果數(shù)據(jù)不匹配模式胆剧,它就會被濾掉。
在Linux中,有兩種流行的正則表達(dá)式引擎:
? POSIX基礎(chǔ)正則表達(dá)式(basic regular expression秩霍, BRE)引擎
? POSIX擴(kuò)展正則表達(dá)式(extended regular expression篙悯, ERE)引擎

BRE模式--純文本
正則表達(dá)式第一條原則就是:'正則表達(dá)式模式都區(qū)分大小寫。

$ echo "The books are expensive" | sed -n '/book/p'
The books are expensive

BRE模式--特殊字符
正則表達(dá)式識別的特殊字符包括:

.*[]^${}\+?|()

特殊字符作為文本字符铃绒,就必須轉(zhuǎn)義鸽照,轉(zhuǎn)義字符:是反斜線(\)。

$ echo "3 / 2" | sed -n '/\//p'
3 / 2

BRE模式--錨字符

  1. 鎖定在行首
    脫字符(^)定義從數(shù)據(jù)流中文本行的行首開始的模式颠悬。
$ echo "This ^ is a test" | sed -n '/s ^/p'
This ^ is a test

// 如果指定正則表達(dá)式模式時只用了脫字符矮燎,就不需要用反斜線來轉(zhuǎn)義。但如果你在模式中先指定了脫字符赔癌,隨后還有其他一些文本诞外,那么你必須在脫字符前用轉(zhuǎn)義字符。

  1. 鎖定在行尾
    特殊字符美元符($)定義了行尾錨點灾票。
$ echo "This is a good book" | sed -n '/book$/p'
This is a good book

// 要想匹配峡谊,文本模式必須是行的最后一部分。比如 sed -n '/boo$/p' 就不能實現(xiàn)匹配

  1. 組合錨點
    行首和行尾同時使用刊苍。
$ cat data5
This is one test line.
This is another test line.
$ sed '/^$/d' data5
This is one test line.
This is another test line.

BRE模式--點號字符
特殊字符點號用來匹配除換行符之外的任意單個字符既们。它必須匹配一個字符,如果在點號字符的位置沒有字符正什,那么模式就不成立啥纸。

$ cat data6
This is a test of a line.
The cat is sleeping.
That is a very nice hat.
This test is at line four.
at ten o'clock we'll go home.
$ sed -n '/.at/p' data6
The cat is sleeping.
That is a very nice hat.
This test is at line four.
// 'cat' 'hat' ' at' 都可以匹配;而'a t'不能匹配埠忘。

BRE模式--字符組
字符組中必須有個字符來匹配相應(yīng)的位置。

$ cat data7
This line doesn't contain a number.
This line has 1 number on it.
This line a number 2 on it.
This line has a number 4 on it.
$ sed -n '/[0123]/p' data7
This line has 1 number on it.
This line a number 2 on it.

如果要確保只匹配五位數(shù)馒索,就必須將匹配的字符和其他字符分開莹妒,要么用空格,要么指明它們就在行首和行尾绰上。

$ sed -n '
> /^[0123456789][0123456789][0123456789][0123456789][0123456789]$/p
> ' data8
60633
46201
22203
// 過濾出data8中只有5個字符的郵編旨怠。

字符組的一個極其常見的用法是"解析拼錯的單詞",比如用戶表單輸入的數(shù)據(jù)蜈块。

$ cat data9
I need to have some maintenence done on my car.
I'll pay that in a seperate invoice.
After I pay for the maintenance my car will be as good as new.
$ sed -n '
> /maint[ea]n[ae]nce/p
> /sep[ea]r[ea]te/p
> ' data9
I need to have some maintenence done on my car.
I'll pay that in a seperate invoice.
After I pay for the maintenance my car will be as good as new.

BRE模式--排除型字符組
可以尋找組中沒有的字符鉴腻,而不是去尋找組中含有的字符。

$ sed -n '/[^ch]at/p' data6
This test is at line four.

BRE模式--特殊的字符組
組 描 述

[[:alpha:]] 匹配任意字母字符百揭,不管是大寫還是小寫
[[:alnum:]] 匹配任意字母數(shù)字字符0~9爽哎、 A~Z或a~z
[[:blank:]] 匹配空格或制表符
[[:digit:]] 匹配0~9之間的數(shù)字
[[:lower:]] 匹配小寫字母字符a~z
[[:print:]] 匹配任意可打印字符
[[:punct:]] 匹配標(biāo)點符號
[[:space:]] 匹配任意空白字符:空格、制表符器一、 NL课锌、 FF、 VT和CR
[[:upper:]] 匹配任意大寫字母字符A~Z

$ echo "abc" | sed -n '/[[:digit:]]/p'
$
$ echo "abc" | sed -n '/[[:alpha:]]/p'
abc
$ echo "abc123" | sed -n '/[[:digit:]]/p'
abc123
$ echo "This is, a test" | sed -n '/[[:punct:]]/p'
This is, a test

BRE模式--區(qū)間

可以用單破折線符號在字符組中表示字符區(qū)間。

$ sed -n '/^[0-9][0-9][0-9][0-9][0-9]$/p' data8
60633
46201
45902

也適用于字母渺贤。

$ sed -n '/[c-h]at/p' data6
The cat is sleeping.
That is a very nice hat.

可以在單個字符組指定多個不連續(xù)的區(qū)間雏胃。

$ sed -n '/[a-ch-m]at/p' data6
The cat is sleeping.
That is a very nice hat.

BRE模式--星號
在字符后面放置星號表明該字符必須在匹配模式的文本中出現(xiàn)0次或多次。

$ echo "I ate a potatoe with my lunch." | sed -n '/potatoe*/p'
I ate a potatoe with my lunch.

將點號特殊字符和星號特殊字符組合起來志鞍。這個組合能夠匹配任意數(shù)量的任意字符瞭亮。它通常用在數(shù)據(jù)流中兩個可能相鄰或不相鄰的文本字符串之間。

$ echo "this is a regular pattern expression" | sed -n '
> /regular.*expression/p'
this is a regular pattern expression

擴(kuò)展--問號
問號表明前面的字符可以出現(xiàn)0次或1次固棚,但只限于此统翩。它不會匹配多次出現(xiàn)的字符。

$ echo "bt" | gawk '/be?t/{print $0}'
bt
$ echo "bet" | gawk '/be?t/{print $0}'
bet

擴(kuò)展--加號
加號表明前面的字符可以出現(xiàn)1次或多次玻孟,但必須至少出現(xiàn)1次唆缴。如果該字符沒有出現(xiàn),那么模式就不會匹配黍翎。

$ echo "beeet" | gawk '/be+t/{print $0}'
beeet
$ echo "beet" | gawk '/be+t/{print $0}'
beet
$ echo "bet" | gawk '/be+t/{print $0}'
bet
$ echo "bt" | gawk '/be+t/{print $0}'
$

擴(kuò)展--花括號
間隔(interval)面徽,可以用兩種格式來指定區(qū)間。
? m:正則表達(dá)式準(zhǔn)確出現(xiàn)m次匣掸。
? m, n:正則表達(dá)式至少出現(xiàn)m次趟紊,至多n次。
這個特性可以精確調(diào)整字符或字符集在模式中具體出現(xiàn)的次數(shù)碰酝。
// 默認(rèn)情況下霎匈, gawk程序不會識別正則表達(dá)式間隔。必須指定gawk程序的--re- interval命令行選項才能識別正則表達(dá)式間隔送爸。

$ echo "bt" | gawk --re-interval '/be{1}t/{print $0}'
$
$ echo "bet" | gawk --re-interval '/be{1}t/{print $0}'
bet
$ echo "beet" | gawk --re-interval '/be{1}t/{print $0}'
$

字符e可以出現(xiàn)1次或2次铛嘱,這樣模式就能匹配;否則袭厂,模式無法匹配:

$ echo "bet" | gawk --re-interval '/be{1,2}t/{print $0}'
bet
$ echo "beet" | gawk --re-interval '/be{1,2}t/{print $0}'
beet

擴(kuò)展--管道符號
管道符號允許你在檢查數(shù)據(jù)流時墨吓,用邏輯OR方式指定正則表達(dá)式引擎要用的兩個或多個模式。
使用管道符號的格式如下:

    expr1|expr2|...
$ echo "The cat is asleep" | gawk '/cat|dog/{print $0}'
The cat is asleep
$ echo "The dog is asleep" | gawk '/cat|dog/{print $0}'
The dog is asleep
$ echo "The sheep is asleep" | gawk '/cat|dog/{print $0}'
$

這個例子會匹配數(shù)據(jù)流文本中的cat纹磺、 hat或dog帖烘。

$ echo "He has a hat." | gawk '/[ch]at|dog/{print $0}'
He has a hat.

擴(kuò)展--表達(dá)式分組
可以用圓括號()進(jìn)行分組。

$ echo "Sat" | gawk '/Sat(urday)?/{print $0}'
Sat
$ echo "Saturday" | gawk '/Sat(urday)?/{print $0}'
Saturday

結(jié)尾的urday分組以及問號橄杨,使得模式能夠匹配完整的Saturday或縮寫Sat秘症。
將分組和管道符號一起使用來創(chuàng)建可能的模式匹配組是很常見的做法:

$ echo "cat" | gawk '/(c|b)a(b|t)/{print $0}'
cat
$ echo "cab" | gawk '/(c|b)a(b|t)/{print $0}'
cab
$ echo "bat" | gawk '/(c|b)a(b|t)/{print $0}'
bat
$ echo "bab" | gawk '/(c|b)a(b|t)/{print $0}'
bab
$ echo "tab" | gawk '/(c|b)a(b|t)/{print $0}'
$
$ echo "tac" | gawk '/(c|b)a(b|t)/{print $0}'
$

總結(jié)與補充

基本正則

grep 'partern'

擴(kuò)展正則

grep -E 'partern'

perl正則(更強的正則)

grep -P 'partern'

1.必記的常用元字符:

.匹配除換行符以外的任意字符
\w 匹配字母或數(shù)字或下劃線或漢字 \W表示與之相反
\s匹配任意的空白符\S表示與之相反
\d匹配數(shù)字\D表示與之相反
\b匹配單詞的開始或結(jié)束\B表示與之相反
^匹配字符串的開始
$匹配字符串的結(jié)束
[x] 匹配字符x [^x]表示出來字符x以外的任意字符
[aeiou] 匹配英語中的元音字母 [^aeiou]表示除了元音字母以外的所有字符

實例

[root@hadoop ~]# cat test.txt
hello
998

@#$
44.5
nihao ll
[root@hadoop ~]# cat test.txt | grep -P '\w'
hello
998
44.5
nihao ll
[root@hadoop ~]# cat test.txt | grep -P '\W'
@#$
44.5
nihao ll
[root@hadoop ~]# cat test.txt | grep -P '\s'
nihao ll
[root@hadoop ~]# cat test.txt | grep -P '\S'
hello
998
@#$
44.5
nihao ll
[root@hadoop ~]# cat test.txt | grep -P '\d'
998
44.5
[root@hadoop ~]# cat test.txt | grep -P '\D'
hello
@#$
44.5
nihao ll
[root@hadoop ~]# cat test.txt | grep -P '\b'
hello
998
44.5
nihao ll
[root@hadoop ~]# cat test.txt | grep -P '\B'
hello
998

@#$
44.5
nihao ll
[root@hadoop ~]# cat test.txt | grep -P '^$'

[root@hadoop ~]# 

2.必記的常用限定符

  • 重復(fù)零次或更多次
  • 重復(fù)一次或更多次
    ? 重復(fù)零次或一次
    {n} 重復(fù)n次
    {n,} 重復(fù)n次或更多次
    {n,m} 重復(fù)n到m次

3.必記的常用分組語法

小括號表示一個子表達(dá)式,匹配這個子表達(dá)式也就是捕獲匹配到的文本式矫,默認(rèn)情況下乡摹,每個分組會自動擁有一個組號,

規(guī)則是:從左向右采转,以分組的左括號為標(biāo)志趟卸,第一個出現(xiàn)的分組的組號為1,第二個為2,以此類推锄列,
組號分配過程是要從左向右掃描兩遍的:第一遍只給未命名組分配图云,第二遍只給命名組分配--因此所有命名組的組號都大于未命名的組號

3.1捕獲
(exp) 匹配exp,并捕獲文本到自動命名的組里 \b(\w+)\b\s+\1\b可以用來匹配重復(fù)的單詞,像go go, 或者kitty kitty

[root@hadoop ~]# echo 'kitty kitty' | grep -oE '\b(\w+)\b\s+\1\b'
kitty kitty

(?<name>exp)匹配exp,并捕獲文本到名稱為name的組里邻邮,也可以寫成(?'name'exp)

上面的正則指定組名竣况,可以寫成\b(?<Word>\w+)\b\s+\k<Word>\b
(?:exp) 匹配exp,不捕獲匹配的文本,也不給此分組分配組號

[root@hadoop ~]# echo 'kitty kitty' | grep -oP '\b(?<wox>\w+)\b\s+\k<wox>\b'
kitty kitty

(?:@\w)binguo\w匹配@開頭包含binguo的字符串
(?:exp)不會改變正則表達(dá)式的處理方式筒严,只是這樣的組匹配的內(nèi)容不會像前兩種那樣被捕獲到某個組里面丹泉,也不會擁有組號

3.2零寬斷言
(?=exp) 匹配exp前面的位置
\b\w+(?=ing\b) I'm singing while you're dancing 匹配sing和danc

(?<=exp)匹配exp后面的位置
(?<=\bre)\w+\b reading a book 匹配ading

[root@hadoop ~]# ifconfig | grep -oP '(?<=inet addr:).*(?=Bcast)'
192.168.121.128  
[root@hadoop ~]# ifconfig | grep -oP '(?=inet addr:).*(?<=Bcast)'
inet addr:192.168.121.128  Bcast
[root@hadoop ~]# ifconfig | grep -oP '(?<=inet addr:).*(?<=Bcast)'
192.168.121.128  Bcast

(?<=\s)\d+(?=\s)匹配以空白符間隔的數(shù)字(再次強調(diào),不包括這些空白符)

[root@hadoop ~]# echo "nihao 9527 hello" | grep -P '(?<=\s)\d+(?=\s)'
nihao 9527 hello

(?!exp) 匹配后面跟的不是exp的位置
需求:獲取不是.exe后綴文件不含后綴的文件名

[root@hadoop ~]# cat files.test 
notexefile1.txt
exefile1.exe
exefile2.exe
exefile3.exe
notexefile2.php
notexefile3.sh
[root@hadoop ~]# cat files.test | grep -oP '(.+)(?!\.exe)\.[\S]+$'
notexefile1.txt
notexefile2.php
notexefile3.sh

(?<!exp)匹配前面不是exp的位置
需求:獲取不是name參數(shù)的值

[root@hadoop ~]# cat form.txt 
name=zhangsan
password=123456
---------------
age=26
sex=man
[root@hadoop ~]# cat form.txt | grep -oP '^[^=]+=(?<!name=)(.+)'
password=123456
age=26
sex=man

3.3注釋
(?#comment)這種類型的分組不對正則表達(dá)式的處理產(chǎn)生任何影響鸭蛙,用于提供注釋讓人閱讀

4.必記的懶惰限定符
*? 重復(fù)任意次摹恨,但盡可能少重復(fù)
+? 重復(fù)1次或更多次,但盡可能少重復(fù)

貪婪匹配:在使整個表達(dá)式能得到匹配的前提下娶视,匹配盡可能多的字符
a.*b晒哄,它將會匹配最長的以a開始,以b結(jié)束的字符串肪获。如果用它來搜索aabab的話寝凌,它會匹配整個字符串a(chǎn)abab。

懶惰(非貪婪)匹配:

也就是匹配盡可能少的字符孝赫,《2.必記的常用限定符》提到的限定符都可以被轉(zhuǎn)化為懶惰匹配模式较木,只要在它后面加上一個問號?
a.*?b,匹配最短的青柄,以a開始伐债,以b結(jié)束的字符串。

如果把它應(yīng)用于aabab的話致开,它會匹配aab(第一到第三個字符)和ab(第四到第五個字符)
為什么第一個匹配的是aab(第一到第三個字符)而不是ab(第二到第三個字符)?
簡單地說峰锁,因為正則表達(dá)式有另一條規(guī)則,比懶惰/貪婪規(guī)則的優(yōu)先級更高:最先開始的匹配擁有最高的優(yōu)先權(quán)

[root@hadoop ~]# echo '<div>test1</div>bb<div>test2</div>' | grep -oP '<div>.*</div>'
<div>test1</div>bb<div>test2</div>
[root@hadoop ~]# echo '<div>test1</div>bb<div>test2</div>' | grep -oP '<div>.*?</div>'
<div>test1</div>
<div>test2</div>

參考正則表達(dá)式30分鐘入門教程

闖關(guān)模式實踐

http://regex.alf.nu 闖關(guān)模式練習(xí)正則表達(dá)式喇喉,完成一個個正則匹配的測驗
http://regexone.com/ 通過實際練習(xí)掌握正則表達(dá)式
https://regexcrossword.com/ 正則挑戰(zhàn)祖今,有不同難度校坑,很豐富
http://callumacrae.github.io/regex-tuesday/ 正則挑戰(zhàn)拣技,完成正則匹配要求

作者:豆約翰
鏈接:http://www.reibang.com/p/e48e2fcd14ff
來源:簡書
簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處耍目。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末膏斤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子邪驮,更是在濱河造成了極大的恐慌莫辨,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異沮榜,居然都是意外死亡盘榨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門蟆融,熙熙樓的掌柜王于貴愁眉苦臉地迎上來草巡,“玉大人,你說我怎么就攤上這事型酥∩胶” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵弥喉,是天一觀的道長郁竟。 經(jīng)常有香客問我,道長由境,這世上最難降的妖魔是什么棚亩? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮藻肄,結(jié)果婚禮上蔑舞,老公的妹妹穿的比我還像新娘。我一直安慰自己嘹屯,他們只是感情好攻询,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著州弟,像睡著了一般钧栖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上婆翔,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天拯杠,我揣著相機與錄音,去河邊找鬼啃奴。 笑死潭陪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的最蕾。 我是一名探鬼主播依溯,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瘟则!你這毒婦竟也來了黎炉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤醋拧,失蹤者是張志新(化名)和其女友劉穎慷嗜,沒想到半個月后淀弹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡庆械,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年薇溃,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缭乘。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡痊焊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出忿峻,到底是詐尸還是另有隱情薄啥,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布逛尚,位于F島的核電站垄惧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏绰寞。R本人自食惡果不足惜到逊,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望滤钱。 院中可真熱鬧觉壶,春花似錦、人聲如沸件缸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽他炊。三九已至争剿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痊末,已是汗流浹背蚕苇。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留凿叠,地道東北人涩笤。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像盒件,于是被迫代替她去往敵國和親蹬碧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 正則表達(dá)式:定義的模式模板(pattern template)履恩,Linux工具可以用它來過濾文本锰茉。如果匹配了定義的...
    數(shù)據(jù)萌新閱讀 188評論 0 0
  • 正則表達(dá)式:定義的模式模板(pattern template)呢蔫,Linux工具可以用它來過濾文本切心。如果匹配了定義的...
    Arroganter閱讀 265評論 0 0
  • 正則表達(dá)式到底是什么東西飒筑?字符是計算機軟件處理文字時最基本的單位,可能是字母绽昏,數(shù)字协屡,標(biāo)點符號,空格全谤,換行符肤晓,漢字等...
    獅子挽歌閱讀 2,147評論 0 9
  • 注:本篇文章只為方便查看,特此保留认然,如有冒犯补憾,敬請諒解!>碓薄盈匾! 本文目標(biāo) 30分鐘內(nèi)讓你明白正則表達(dá)式是什么,并對它...
    阿杰Alex閱讀 1,483評論 0 10
  • 1.redis 作為存儲服務(wù)器### redis.js redis-user-dao.js 2.redis作為se...
    Tony_HQ閱讀 1,626評論 0 5