談談正則表達式這個東西:
我想作為一個程序員,正則表達式大家絕對不陌生。
正則表達式好像一個有限則動機。主要作用是匹配,但是同時因為這個功能,我們可以擴展很多其他用法
像很多語言都引人了正則表達式:java,C#等面向對象語言,更多的是腳本語言。
另外我們常用的一些工具都引入了這個正則表達式:sed,awk,gawk,grep
包括我們的C語言,它這種引入了一部分基礎的正則表達式,我們一會會見到:
正則表達式是用正則表達式引擎實現的。正則表達式引擎是解釋正則表達式模式並使用這些模式進行文字或者命令匹配的底層軟件
學過編譯原理的都知道DFA,和NFA的概念,這是我們編譯過程中語法匹配的兩大模式。他們的原理和正則表達式一樣。
正則表達式就是根據這樣分類:我們之關注Linux
在Linux,有兩種流行的正則表達式引擎:
POSIX基本正則表達式引擎(BRE)
POSIX擴展正則表達式引擎(ERE)
大多數Linux工具都至少符合BRE
下面先看一下BRE基本成分,然后看看它在不同方面的不同應用
BRE主要有一些特殊字符組成:這些特殊字符有: .*[]^${}\+?|(),下面我們一一學習:但是有一點特殊:不能直接使用單斜線(/)要用反義字符表示包括除法符號(/)
1,錨字符
行首鎖定:^ 定義從數據流中文本行的行首開始的模式。只能是行首
行尾鎖定:$定義了行尾錨點
兩種可以匹配 使用 達到特殊的用處
2,點字符
. 用來匹配除了換行符以外的任意單字符
3,字符數組
[] 可以在此數組中定義你想匹配的任意字符也可以前后配合使用用於交叉匹配
4,排除字符組
[^] 就是字符數組的反義詞,匹配的時候不匹配數組中的字符
5,區間:
[]可以用次符號表示區間 [0-9] [a-z]等等進行匹配
6,特殊字符數組:這些定義好的可以使用
[[:alpha:]] 匹配任意字母字符,不區分大小寫(都包括)
[[:alnum:]] 匹配任意字母數字字符0-9,A-Z , a-z
[[:blank:]] 匹配空格或者制表符
[[:digit:]] 匹配0-9數字
[[:lower:]] 匹配小寫字母
[[:print:]] 匹配可打印字符
[[:punct:]] 匹配標點符號
[[:space:]] 匹配任意空白:空格,制表符,NL,NF,VT,和CR
[[:upper:]] 匹配任意大寫字母
7,星號:
在匹配文本后面表示出現0次或多次:
ERE包括一些特殊的擴展用法,awk工具能識別但是sed工具不能
1,問號
文本后面加上?,表示匹配0次或者1次
2,加號
匹配文本后加上+,表示至少匹配一次
3,化括號
(m,n)至少出現m此,最多出現n次
4,管道符號
類似or符號,任意匹配就可以
5,聚合表達式
(),用該符號表示,相當於一個准字符
下面我們來做實驗,介紹正則表達式常用的地方及場景
1,sed工具
sed的全程為stream editor,俗稱流編輯器。和傳說中的交互式文本編輯器正好相反
語法:
sed options script file
-e script 在處理輸入時,將script中指定的命令添加到運行的命令中
-f file 在處理輸入時,將file中指定的命令添加到運行的命令中
-n 不要為每個命令生成輸出,等待print命令來輸出,起到過濾的意思
下面一一道來:
e1:
我們從這三個例子中可以看出,sed -n選項的過濾作用,可以看到sed的流處理是怎么實現的。其中s是sed流處理過程中替換的標識,后面還有很多eg:d刪除,p打印等等見到再說
///一共是三個,前面兩個中間是被替換的文本,后面兩個中間是要替換的文本
要在sed命令行上執行多條指令,則加上-e選項就可以了,相當於前面的插入命令,中間加上“;”號,其他不正確的寫法看下圖
e2:
上面介紹了幾種常見的正確和錯誤寫法,其中最后一種主要是根據’號的作用,很類似python語言中的長句子(... ...)
而且還有一種現象,我們的匹配是完全的,只要有匹配的就替換,下面的從文本中讀取編輯命令可以看出:
e3:
結果出來了,仔細看的就會發現。所謂完全匹配還是有一定的差別。有一個限制條件是:每行之替換一個!!!
如果我們想讓它們都替換怎么辦,簡單,加上全集控制符就可以了/g,看它是怎么只手回天的
e4:
怎么樣,控制性很高吧
sed的匹配模式語法:
s/pattern/replacement/flags
有四種可以替換標記:
>數字,標識將替換第幾處匹配的地方
>g , 標識全局替換,只要出現就替換
>p ,標識原來行的內容打印出來
>w file ,將替換的結果寫的文件file中
數字:
e5:
g和p:
e6:
我們從例子中可以清晰的看出區別
下面看看我們的另類一點的 寫文件:
e7:
自己看,不解釋,標志在感情可以接受的范圍內可以用多個
另外我們發現,如果我們替換的是字符串並且字符串里面是一個路徑(里面含有/)怎么辦?
Look me:
e8:
我們看出了什么? 很明顯,有路徑必須用\符合轉義。當然也可以換作其他分割符"!"
而且目前只有"!"可以勝任,其他的(如例子#,@)雖然沒有語法錯誤,但是不識別
sed使用地址:
sed中有兩種行尋址:
1,行的數字范圍
2,用文本模式來過濾出某行
都可以用相似方式實現:
[address] command
address {
command1
command2
command3
}
數字行尋址:
e9:
結果很明顯,不做太多解釋。$前面也介紹過
文本過濾模式過濾:
/pattern/command
e10:
當然組合命令也是可以的,比較繁
一個新的sed標識:d(elete)
看例子:
e11:
刪除可以根據上面提到過的兩種匹配模式
還有你甚至可以這樣刪除:
e12:
但是這么做有可能造成意外.第一次指定模式會"打開"行刪除功能,第二個模式會"關閉"行刪除功能.意思是會刪除它們之間的元素
另外,只要匹配了打開功能,就開始刪除.結果可能讓你發瘋:
e13:
sed的插入和追加:
插入命令i會在指定行之前增加一行
追加命令a會在指定行之后加入一個新行
令人納悶的它們格式:
sed '[address]command\
new line'
例子:
e14:
$指最后一行:
e15:
同理可以在文本第一行插入.
sed 的修改:
同理修改要指定行地址
e16:
sed 轉換命令
[address]y/inchars/outchars/ 等長轉換
轉換是一個全局命令,可以轉化匹配的一切:
e17:
sed的打印
>p 打印文本行
>= 打印行號
>l 列出行
打印行:
e18:
打印行號:
e19:
列出行: 列出數據流中所有字符,包括可打印和不可打印的字符
e20:
sed的文本保存
[address]w filename
sed '1,2w test' file 把file文件的1,2行讀到test中.
可以用-n選項禁止顯示在屏幕上
sed的讀文件
[address]r filename
sed '3r test' file 讀出test內容插入到file文件的第3行后面
sed '/number/r test' file 讀出test內容,插入到file中含number行后面
sed '$r test' file 把test內容插到file文件最后