本文主要介紹 Linux 系統的兩個神級工具:sed 和 awk ,他們是Linux高手們必備的技能,很值得咱們去研究的東西。正則表達式
這裏是我在網上書上收集的相關資料,由於這兩個工具頗有名也很重要,因此這些資料會幫助我更好的瞭解和熟悉它們。shell
在《sed and awk》一書中(1.2 A Stream Editor)的解釋是:編程
Sed本質上是一個編輯器,可是它是非交互式的,這點與VIM不一樣;同時它又是面向字符流的,輸入的字符流通過Sed的處理後輸出。這兩個特性使得Sed成爲命令行下面很是有用的一個處理工具。bash
Sed自己是一個管道命令,能夠分析 standard input 的,主要是用來分析關鍵字的使用、統計等,此外還能夠將數據進行替換、刪除、心中、選取特定行等功能。編程語言
sed命令的語法以下所示:編輯器
sed [-nefr] [動做]
參數說明:工具
-n : 使用安靜模式,通常全部來自STDIN的數據會被列出到屏幕上,可是 -n 在能夠只列出通過 sed 處理過的那一行。測試
-e : 直接在命令行模式上進行 sed 的動做編輯。命令行
-f : 直接將 sed 的動做卸載一個文件內, -f filename 則能夠執行 filename 內的 sed 動做。設計
-r : sed 的動做支持的是擴展型正則表達式的語法(默認是基礎正則表達式語法)。
-i : 直接修改讀取的文件內容,而不是由屏幕輸出。
動做說明: [n1],[n2] function
n1,n2:不見得會存在,通常表明選擇進行動做的行數。
舉例來講:若是個人動做是須要在 10 到 20 行之間進行的,則「10,20[動做行爲]」
function 有下面這些參數:
a:新增,a 的後面能夠接字符串,而這些字符串會在新的一行出現(目前的下一行)。
c:替換,c 的後面能夠接字符串,這些字符串能夠替換n1,n2之間的行!
d:刪除,由於是刪除,因此 d 後面一般不接任何參數。
i:插入,i 的後面能夠接字符串,而這些字符串會在新的一行出現(目前的上一行)。
p:打印,也就是將某個選擇的數據打印出來,一般 p 會與參數 sed -n 一塊兒運行。
s:替換,能夠直接進行替換工做。一般這個 s 的動做能夠匹配正則表達式!
例如:1,20s/old/new/g 就是。
以行爲單位的新增或刪除功能
案例(一)
nl /etc/passwd | sed '2,5d'
說明:
sed 的動做爲 '2,5d',那個 d 就是刪除,命令運行的效果就是把2~5行給刪除。
須要注意的是,本來應該是要執行 sed -e 纔對,沒有 -e 也行。
另外還須要注意的一點:sed 後面接的動做,請務必要以 '' 兩個單引號括住。
若是你只想刪除第二行,那麼命令就是:nl /etc/passwd | sed '2d'。
若是你想刪除第三行到最後一行,那麼就能夠這麼寫:nl /etc/passwd | sed '3,$d'
注:$表示最後一行。
案例(二)
nl /etc/passwd | sed '2a drink tea'
說明:
命令執行的效果就是在第二行後面(也就是第三行)加上「drink tea」字樣。
若是你想在第二行前面加上字符串,那麼你能夠這樣:nl /etc/passwd | sed '2i drink tea'
注:2a 中的 a 是指第二行後面,而 2i 中的 i 則是指第二行的前面。
案例(三)
nl /etc/passwd | sed '2a drink tea or ......\ drink beer'
說明:
上面的命令的執行效果是在第二行後面加入2行字。
在每一行的後面必需要以反斜槓 來進行新行的增長。
以行爲單位的替換與顯示功能
案例(一)
nl /etc/passwd | sed '2, 5c No 2-5 number'
說明:
上面的命令的執行效果是將第2~5行的內容替換成「No 2-5 number」
案例(二)
nl /etc/passwd | sed -n '5,7p'
說明:
上面的命令執行的效果是僅列出文件中的第5~7行的內容。
命令中的 -n 表明的是安靜模式!可是這個參數建議加上。
案例(三)
sed 's/要被替換的內容/新的內容/g'
說明:
以上命令執行的效果就是替換掉指定內容。
案例(四)
下面是記錄一次獲取IP數據的過程:
第一步:先查看源信息,利用 /sbin/ifconfig 查詢 IP。
/sbin/ifconfig eth0
注:咱們的目的是要得到IP數據,那麼先利用關鍵字找出那一行。
第二步:利用關鍵字配合 grep 選取出關鍵的一行數據。
/sbin/ifconfig eth0 | grep 'inet addr'
注:由於只須要IP數據,因此接下來就是把不須要的內容都刪掉,那麼就須要一個正則表達式來幫助實現:
^.*inet addr:
第三步:將 IP 前面的部分予以刪除
/sbin/ifconfig eth0 | grep 'inet addr' | \ sed 's/^.*inet addr://g'
注:上面的命令就把 IP 前面的數據刪掉了,那麼接下來就是把 IP 後面的數據也刪掉,此時的正則表達式則是:
Bcast.*$
第四步:將 IP 後面的部分予以刪除
/sbin/ifconfig eth0 | grep 'inet addr' | \ sed 's/^.*inet addr://g' | sed 's/Bcast.*$//g'
這樣就能把 IP 截取出來了~~~
案例(五)
這裏主要是展現 sed 與正則表達式的配合使用。
假設我想在一個文件(你本身新建或者已有的,主要是測試而已)獲取MAN字樣的那幾行數據,可是#在內的批註我不須要,並且空白行也不要。
第一步:先使用 grep 將關鍵字 MAN 所在行取出來。
cat /home/man.config | grep 'MAN'
第二步:刪除掉批註以後的數據。
cat /home/man.config | grep 'MAN' | sed 's/#.*$//g'
第三步:那麼接下來就是把空白行刪除掉。
cat /home/man.config | grep 'MAN' | sed 's/#.*$//g' | \ sed '^$/d'
直接修改文件內容(慎重)
首先要特別提醒的是,要練習 sed 修改文件內容的時候不能用任何系統配置文件,最好是本身新建一個測試文原本測試練習。
案例(一)
sed -i '/s\.$/\!/g' test.txt
說明:
上面命令執行效果是利用 sed 將test.txt內的每一行結尾爲「.」 的換成 !
命令中的 -i 參數可讓你的 sed 直接去修改後面接的文件內容,而不是由屏幕輸出。
案例(二)
sed -i '$a # This is a test' test.txt
說明:
上面命令執行的效果是利用 sed 直接在test.txt最後一行加入 「This is a test」。
因爲 $ 表明的是最後一行,而 a 的操做是新增,所以該文件最後新增。
簡單來講,awk 是一個數據處理工具。
相比於 sed 經常做用於一整行的處理,awk 則比較傾向於將一行分紅數個「字段」來處理。所以,awk 至關適合處理小型數據的數據處理。
對於編程語言來說,awk 是一種便於使用且表達能力強的程序設計語言,可應用於各類計算和數據處理任務。
基本語法
awk '條件類型1{動做1} 條件類型2{動做2} ...' filename
awk 後面接兩個單引號病加上大括號{}來設置想要對數據進行的處理動做。
awk 能夠處理後續接的文件,也能夠讀取來自籤個命令的 standardoutput。
如前面說的,awk 主要是處理每一行的字段內的數據,而默認的字段的分隔符爲空格鍵或者[tab]鍵。 好比:
last -n 5 // 僅取出登錄者的數據前五行(last 能夠將登錄者的數據取出來)
若是我還要在這些信息中取出:帳號與登錄者的IP,且帳號與IP之間以[tab]隔開,那麼能夠這麼改命令:
last -n 5 | awk '{print $1 "\t" $3}'
上面是 awk 最常使用的動做,經過 print 的功能來說字段的數據列出來,字段的分割則以空格鍵或者[tab]按鍵來隔開。
上面的例子中,在每一行的每一個字段都是有變量名稱的,那就是$1,$2等變量名稱。
備註:$1 指的就是第一列,可是 $0 則是表明一整行(第一行)。
上面的例子中整個awk的處理流程:
(1)讀入第一行,並將第一行的數據填入$0,$1,$2等變量中; (2)依據條件類型的限制,判斷是否須要進行後面的動做; (3)昨晚全部的動做與條件類型; (4)若還有後續的「行」的數據,則重複上面1~3的不知,直到全部的數據都讀完爲止。
注:awk是以行爲一次處理的單位,而以字段最小的處理單位。
對於上面的案例指令 last -n 5 ... 來說,有幾點須要注意的:
列出每一行的帳號(就是$1)。
列出目前處理的行數(那就是 awk 內的 NR 變量)。
而且說明,該行有多少個字段(就是 awk 內的 NF 變量)。
注意: awk 後續的全部動做都是以單引號 「'」 括住的,因爲單引號與雙引號都必須是成對的,因此 awk 的格式內容如查想要以 print 打印時,記得非變量的文字部分,包含一小節 printf 提到的格式中,都須要使用雙引號來定義出來,由於單引號已經是 awk 的命令固定用法了。
last -n 5 | awk '{print $1 "\t lines: " NR "\t lines: " NR "\t columes: " NF}'
awk 的運算符
大於: >
小於: <
大於或等於: >=
小於或等於: <=
等於: ==
不等於: !=
值得關注的是那個等於 「==」 的符號,由於:
邏輯運算上面也就是所謂的大於,小於,等於等判斷式上面,習慣上是以「==」來表示的。
若是是直接給與一個值,例如變量設置時,就直接使用 = 而已。
案例(一)
cat /etc/passwd | \ awk '{FS=":"} $3 < 10 {print $1 "\t " $3}'
說明:上面的指令運行的效果是查閱第三列小於10如下的數據,而且僅列出帳號與第三列。(在 /etc/passwd 當中是以冒號「:」來做爲字段的風,該文件中第一字段爲帳號,第三字段則是UID)
案例(二)
cat /etc/passwd | \ awk 'BEGIN {FS":"} $3 < 10 {print $1 "\t " $3}'
說明:因爲案例一中並無顯示出第一行的數據,那麼此命令則是把第一行也顯示出來了。利用 BEGIN 關鍵字預先設置 awk 的變量。
案例(三)
此外 awk 還能夠進行「計算功能」。
好比有一個文件,內容以下:
name 1st 2nd 3th
小A 1000 1000 1000
小B 2000 2000 2000
小C 3000 3000 3000
那麼怎麼計算每一個人的總額呢?並且還須要格式化輸出,那麼能夠這樣思考:
第一行只是說明,因此第一行不要進行加總(NR==1時處理)。
第二行之後就會有加總的狀況出現(NR>=2之後處理)。
cat test.txt | \ awk 'NR==1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4, "Total" } NR>2{total = $2 + $3 + $4 printf "%10s %10d %10d %10.2f\n", $1, $2, $3, $4, total}'
說明:
全部 awk 的動做(即在{}內的動做),若是有須要多個命令來輔助是,可利用分號「;」間隔,或者直接以[Enter]按鍵來隔開每一個命令,上面則是摁了三次。
邏輯運算中,若是是「等於」的狀況,則務必使用兩個等號「==」!
格式化處輸出時,在 printf 的格式設置當中,務必加上 n ,才能實現分行。
與 bash 、shell 的變量不一樣,在 awk 當中,變量能夠直接使用,不須要加上 $ 符號。