1. 程式人生 > >實驗樓 正則表達式基礎

實驗樓 正則表達式基礎

斜線 擴展 inux 文檔 輸出 ogr 沒有 匹配查找 ram

基本語法:

選擇

|豎直分隔符表示選擇,例如"boy|girl"可以匹配"boy"或者"girl"

數量限定

數量限定除了我們舉例用的*,還有+加號,?問號,如果在一個模式中不加數量限定符則表示出現一次且僅出現一次:

  • +表示前面的字符必須出現至少一次(1次或多次),例如,"goo+gle",可以匹配"gooogle","goooogle"等;
  • ?表示前面的字符最多出現一次(0次或1次),例如,"colou?r",可以匹配"color"或者"colour";
  • *星號代表前面的字符可以不出現,也可以出現一次或者多次(0次、或1次、或多次),例如,“0*42”可以匹配42、042、0042、00042等。

範圍和優先級

()圓括號可以用來定義模式字符串的範圍和優先級,這可以簡單的理解為是否將括號內的模式串作為一個整體。例如,"gr(a|e)y"等價於"gray|grey",(這裏體現了優先級,豎直分隔符用於選擇a或者e而不是gra和ey),"(grand)?father"匹配father和grandfather(這裏體驗了範圍,?將圓括號內容作為一個整體匹配)。

字符描述
\ 將下一個字符標記為一個特殊字符、或一個原義字符。例如,“n”匹配字符“n”。“\n”匹配一個換行符。序列“\\”匹配“\”而“\(”則匹配“(”。
^ 匹配輸入字符串的開始位置。
$ 匹配輸入字符串的結束位置。
{n} n是一個非負整數。匹配確定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的兩個o。
{n,} n是一個非負整數。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等價於“o+”。“o{0,}”則等價於“o*”。
{n,m} m和n均為非負整數,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”將匹配“fooooood”中的前三個o。“o{0,1}”等價於“o?”。請註意在逗號和兩個數之間不能有空格。
* 匹配前面的子表達式零次或多次。例如,zo*能匹配“z”、“zo”以及“zoo”。*等價於{0,}。
+ 匹配前面的子表達式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等價於{1,}。
? 匹配前面的子表達式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do”。?等價於{0,1}。
? 當該字符緊跟在任何一個其他限制符(*,+,?,{n},{n,},{n,m})後面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認的貪婪模式則盡可能多的匹配所搜索的字符串。例如,對於字符串“oooo”,“o+?”將匹配單個“o”,而“o+”將匹配所有“o”。
. 匹配除“\n”之外的任何單個字符。要匹配包括“\n”在內的任何字符,請使用像“(.|\n)”的模式。
(pattern) 匹配pattern並獲取這一匹配的子字符串。該子字符串用於向後引用。要匹配圓括號字符,請使用“\(”或“\)”。
x|y 匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”則匹配“zood”或“food”。
[xyz] 字符集合(character class)。匹配所包含的任意一個字符。例如,“[abc]”可以匹配“plain”中的“a”。其中特殊字符僅有反斜線\保持特殊含義,用於轉義字符。其它特殊字符如星號、加號、各種括號等均作為普通字符。脫字符^如果出現在首位則表示負值字符集合;如果出現在字符串中間就僅作為普通字符。連字符 - 如果出現在字符串中間表示字符範圍描述;如果如果出現在首位則僅作為普通字符。
[^xyz] 排除型(negate)字符集合。匹配未列出的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”。
[a-z] 字符範圍。匹配指定範圍內的任意字符。例如,“[a-z]”可以匹配“a”到“z”範圍內的任意小寫字母字符。
[^a-z] 排除型的字符範圍。匹配任何不在指定範圍內的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”範圍內的任意字符。

優先級為從上到下從左到右,依次降低:

運算符說明
\ 轉義符
(), (?:), (?=), [] 括號和中括號
*、+、?、{n}、{n,}、{n,m} 限定符
^、$、\任何元字符 定位點和序列
 選擇

技術分享

grep模式匹配命令

基本操作

grep命令用於打印輸出文本中匹配的模式串,它使用正則表達式作為模式匹配的條件。

在通過grep命令使用正則表達式之前,先介紹一下它的常用參數:

參數說明
-b 將二進制文件作為文本來進行匹配
-c 統計以模式匹配的數目
-i 忽略大小寫
-n 顯示匹配文本所在行的行號
-v 反選,輸出不匹配行的內容
-r 遞歸匹配查找
-A n n為正整數,表示after的意思,除了列出匹配行之外,還列出後面的n行
-B n n為正整數,表示before的意思,除了列出匹配行之外,還列出前面的n行
--color=auto 將輸出中的匹配項設置為自動顏色顯示

使用正則表達式

使用基本正則表達式,BRE

  • 位置

查找/etc/group文件中以"shiyanlou"為開頭的行

$ grep ‘shiyanlou‘ /etc/group
$ grep ‘^shiyanlou‘ /etc/group
  • 數量
# 將匹配以‘z‘開頭以‘o‘結尾的所有字符串
$ echo ‘zero\nzo\nzoo‘ | grep ‘z.*o‘
# 將匹配以‘z‘開頭以‘o‘結尾,中間包含一個任意字符的字符串
$ echo ‘zero\nzo\nzoo‘ | grep ‘z.o‘
# 將匹配以‘z‘開頭,以任意多個‘o‘結尾的字符串
$ echo ‘zero\nzo\nzoo‘ | grep ‘zo*‘

註意:其中\n為換行符

  • 選擇
# grep默認是區分大小寫的,這裏將匹配所有的小寫字母
$ echo ‘1234\nabcd‘ | grep ‘[a-z]‘
# 將匹配所有的數字
$ echo ‘1234\nabcd‘ | grep ‘[0-9]‘
# 將匹配所有的數字
$ echo ‘1234\nabcd‘ | grep ‘[[:digit:]]‘
# 將匹配所有的小寫字母
$ echo ‘1234\nabcd‘ | grep ‘[[:lower:]]‘
# 將匹配所有的大寫字母
$ echo ‘1234\nabcd‘ | grep ‘[[:upper:]]‘
# 將匹配所有的字母和數字,包括0-9,a-z,A-Z
$ echo ‘1234\nabcd‘ | grep ‘[[:alnum:]]‘
# 將匹配所有的字母
$ echo ‘1234\nabcd‘ | grep ‘[[:alpha:]]‘
# 排除字符
$ $ echo ‘geek\ngood‘ | grep ‘[^o]‘

註意:^放到中括號內為排除字符,否則表示行首。

下面包含完整的特殊符號及說明:

特殊符號說明
[:alnum:] 代表英文大小寫字節及數字,亦即 0-9, A-Z, a-z
[:alpha:] 代表任何英文大小寫字節,亦即 A-Z, a-z
[:blank:] 代表空白鍵與 [Tab] 按鍵兩者
[:cntrl:] 代表鍵盤上面的控制按鍵,亦即包括 CR, LF, Tab, Del.. 等等
[:digit:] 代表數字而已,亦即 0-9
[:graph:] 除了空白字節 (空白鍵與 [Tab] 按鍵) 外的其他所有按鍵
[:lower:] 代表小寫字節,亦即 a-z
[:print:] 代表任何可以被列印出來的字節
[:punct:] 代表標點符號 (punctuation symbol),亦即:" ‘ ? ! ; : # $...
[:upper:] 代表大寫字節,亦即 A-Z
[:space:] 任何會產生空白的字節,包括空白鍵, [Tab], CR 等等
[:xdigit:] 代表 16 進位的數字類型,因此包括: 0-9, A-F, a-f 的數字與字節

使用擴展正則表達式,ERE

要通過grep使用擴展正則表達式需要加上-E參數,或使用egrep

  • 數量
# 只匹配"zo"
$ echo ‘zero\nzo\nzoo‘ | grep -E ‘zo{1}‘
# 匹配以"zo"開頭的所有單詞
$ echo ‘zero\nzo\nzoo‘ | grep -E ‘zo{1,}‘
  • 選擇
# 匹配"www.shiyanlou.com"和"www.google.com"
$ echo ‘www.shiyanlou.com\nwww.baidu.com\nwww.google.com‘ | grep -E ‘www\.(shiyanlou|google)\.com‘
# 或者匹配不包含"baidu"的內容
$ echo ‘www.shiyanlou.com\nwww.baidu.com\nwww.google.com‘ | grep -Ev ‘www\.baidu\.com‘

sed 流編輯器

sed工具在 man 手冊裏面的全名為"sed - stream editor for filtering and transforming text",意即,用於過濾和轉換文本的流編輯器。

sed常用參數介紹

sed 命令基本格式:

sed [參數]... [執行命令] [輸入文件]...
# 形如:
$ sed -i ‘1s/sad/happy/‘ test # 表示將test文件中第一行的"sad"替換為"happy"
參數說明
-n 安靜模式,只打印受影響的行,默認打印輸入數據的全部內容
-e 用於在腳本中添加多個執行命令一次執行,在命令行中執行多個命令通常不需要加該參數
-f filename 指定執行filename文件中的命令
-r 使用擴展正則表達式,默認為標準正則表達式
-i 將直接修改輸入文件內容,而不是打印到標準輸出設備

sed編輯器的執行命令(這裏”執行“解釋為名詞)

[n1][,n2]command
[n1][~step]command
# 其中一些命令可以在後面加上作用範圍,形如:
$ sed -i ‘s/sad/happy/g‘ test # g表示全局範圍
$ sed -i ‘s/sad/happy/4‘ test # 4表示指定行中的第四個匹配字符串

sed執行命令格式:

[n1][,n2]command
[n1][~step]command
# 其中一些命令可以在後面加上作用範圍,形如:
$ sed -i ‘s/sad/happy/g‘ test # g表示全局範圍
$ sed -i ‘s/sad/happy/4‘ test # 4表示指定行中的第四個匹配字符串

其中n1,n2表示輸入內容的行號,它們之間為,逗號則表示從n1到n2行,如果為波浪號則表示從n1開始以step為步進的所有行;command為執行動作,下面為一些常用動作指令:

命令說明
s 行內替換
c 整行替換
a 插入到指定行的後面
i 插入到指定行的前面
p 打印指定行,通常與-n參數配合使用
d 刪除指定行

sed操作舉例

我們先找一個用於練習的文本文件:

$ cp /etc/passwd ~

打印指定行

# 打印2-5行
$ nl passwd | sed -n ‘2,5p‘
# 打印奇數行
$ nl passwd | sed -n ‘1~2p‘

行內替換

# 將輸入文本中"shiyanlou" 全局替換為"hehe",並只打印替換的那一行,註意這裏不能省略最後的"p"命令
$ sed -n ‘s/shiyanlou/hehe/gp‘ passwd

註意: 行內替換可以結合正則表達式使用。

行間替換

$ nl passwd | grep "shiyanlou"
# 刪除第21行
$ sed -n ‘21c\www.shiyanlou.com‘ passwd
(這裏我們只把要刪的行打印出來了,並沒有真正的刪除,如果要刪除的話,請使用-i參數)

awk文本處理語言

AWK是一種用於處理文本的編程語言工具。

awk的一些基礎概念

awk所有的操作都是基於pattern(模式)—action(動作)對來完成的,如下面的形式:

$ pattern {action}

你可以看到就如同很多編程語言一樣,它將所有的動作操作用一對{}花括號包圍起來。其中pattern通常是是表示用於匹配輸入的文本的“關系式”或“正則表達式”,action則是表示匹配後將執行的動作。在一個完整awk操作中,這兩者可以只有其中一個,如果沒有pattern則默認匹配輸入的全部文本,如果沒有action則默認為打印匹配內容到屏幕。

awk命令基本格式

awk [-F fs] [-v var=value] [-f prog-file | ‘program text‘] [file...]

其中-F參數用於預先指定前面提到的字段分隔符(還有其他指定字段的方式) ,-v用於預先為awk程序指定變量,-f參數用於指定awk命令要執行的程序文件,或者在不加-f參數的情況下直接將程序語句放在這裏,最後為awk需要處理的文本輸入,且可以同時輸入多個文本文件。

awk操作體驗

先用vim新建一個文本文檔

$ vim test

包含如下內容:

I like linux
www.shiyanlou.com
  • 使用awk將文本內容打印到終端
# "quote>" 不用輸入
$ awk ‘{
> print
> }‘ test
# 或者寫到一行
$ awk ‘{print}‘ test

說明:在這個操作中我是省略了pattern,所以awk會默認匹配輸入文本的全部內容,然後在"{}"花括號中執行動作,即print打印所有匹配項,這裏是全部文本內容

  • 將test的第一行的每個字段單獨顯示為一行
$ awk ‘{
> if(NR==1){
> print $1 "\n" $2 "\n" $3
> } else {
> print}
> }‘ test

# 或者
$ awk ‘{
> if(NR==1){
> OFS="\n"
> print $1, $2, $3
> } else {
> print}
> }‘ test

說明:你首先應該註意的是,這裏我使用了awk語言的分支選擇語句if,它的使用和很多高級語言如C/C++語言基本一致,如果你有這些語言的基礎,這裏將很好理解。另一個你需要註意的是NROFS,這兩個是awk內建的變量,NR表示當前讀入的記錄數,你可以簡單的理解為當前處理的行數,OFS表示輸出時的字段分隔符,默認為" "空格,如上圖所見,我們將字段分隔符設置為\n換行符,所以第一行原本以空格為字段分隔的內容就分別輸出到單獨一行了。然後是$N其中N為相應的字段號,這也是awk的內建變量,它表示引用相應的字段,因為我們這裏第一行只有三個字段,所以只引用到了$3。除此之外另一個這裏沒有出現的$0,它表示引用當前記錄(當前行)的全部內容。

  • 將test的第二行的以點為分段的字段換成以空格為分技術分享
$ awk -F‘.‘ ‘{
> if(NR==2){
> print $1 "\t" $2 "\t" $3
> }}‘ test

# 或者
$ awk ‘
> BEGIN{
> FS="."
> OFS="\t"  # 如果寫為一行,兩個動作語句之間應該以";"號分開  
> }{
> if(NR==2){
> print $1, $2, $3
> }}‘ test
說明:這裏的-F參數,前面已經介紹過,它是用來預先指定待處理記錄的字段分隔符。我們需要註意的是除了指定OFS我們還可以在print 語句中直接打印特殊符號如這裏的\tprint打印的非變量內容都需要用""一對引號包圍起來。上面另一個版本,展示了實現預先指定變量分隔符的另一種方式,即使用BEGIN,就這個表達式指示了,其後的動作將在所有動作之前執行,這裏是FS賦值了新的"."點號代替默認的" "空格

awk常用的內置變量

變量名說明
FILENAME 當前輸入文件名,若有多個文件,則只表示第一個。如果輸入是來自標準輸入,則為空字符串
$0 當前記錄的內容
$N N表示字段號,最大值為NF變量的值
FS 字段分隔符,由正則表達式表示,默認為" "空格
RS 輸入記錄分隔符,默認為"\n",即一行為一個記錄
NF 當前記錄字段數
NR 已經讀入的記錄數
FNR 當前輸入文件的記錄數,請註意它與NR的區別
OFS 輸出字段分隔符,默認為" "空格
ORS 輸出記錄分隔符,默認為"\n"

實驗樓 正則表達式基礎