您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)sed&awk的基本使用方法是什么,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
sed&awk基本使用方法
sed 工具簡(jiǎn)介
在了解了一些正規(guī)表示法的基礎(chǔ)應(yīng)用之后,再來(lái)呢?呵呵~兩個(gè)東西可以玩一玩的,那就是 sed 跟 awk 了!
這兩個(gè)家伙可是相當(dāng)?shù)挠杏玫陌。∨e例來(lái)說(shuō),鳥(niǎo)哥寫(xiě)的 logfile.sh 分析登錄文件的小程序,絕大部分分析關(guān)鍵詞的取用、統(tǒng)計(jì)等等,就是用這兩個(gè)寶貝蛋來(lái)幫我完成的! 那么你說(shuō),要不要玩一玩?。?! ^_^
我們先來(lái)談一談 sed 好了,基本上, sed 可以分析 Standard Input (STDIN) 的數(shù)據(jù),
然后將數(shù)據(jù)經(jīng)過(guò)處理后,再將他輸出到 standrad out (STDOUT) 的一個(gè)工具。
至于處理呢?可以進(jìn)行取代、刪除、新增、擷取特定行等等的功能呢!很不錯(cuò)吧~ 我們先來(lái)了解一下 sed 的用法,再來(lái)聊他的用途好了!
[root@linux ~]# sed [-nefri] [動(dòng)作]
參數(shù):
-n :使用安靜(silent)模式。在一般 sed 的用法中,所有來(lái)自 STDIN
的數(shù)據(jù)一般都會(huì)被列出到屏幕上。但如果加上 -n 參數(shù)后,則只有經(jīng)過(guò)
sed 特殊處理的那一行(或者動(dòng)作)才會(huì)被列出來(lái)。
-e :直接在指令列模式上進(jìn)行 sed 的動(dòng)作編輯;
-f :直接將 sed 的動(dòng)作寫(xiě)在一個(gè)檔案內(nèi), -f filename 則可以執(zhí)行 filename 內(nèi)的
sed 動(dòng)作;
-r :sed 的動(dòng)作支持的是延伸型正規(guī)表示法的語(yǔ)法。(預(yù)設(shè)是基礎(chǔ)正規(guī)表示法語(yǔ)法)
-i :直接修改讀取的檔案內(nèi)容,而不是由屏幕輸出。
動(dòng)作說(shuō)明: [n1[,n2]]function
n1, n2 :不見(jiàn)得會(huì)存在,一般代表『選擇進(jìn)行動(dòng)作的行數(shù)』,舉例來(lái)說(shuō),如果我的動(dòng)作
是需要在 10 到 20 行之間進(jìn)行的,則『 10,20[動(dòng)作行為] 』
function 有底下這些咚咚:
a :新增, a 的后面可以接字符串,而這些字符串會(huì)在新的一行出現(xiàn)(目前的下一行)~
c :取代, c 的后面可以接字符串,這些字符串可以取代 n1,n2 之間的行!
d :刪除,因?yàn)槭莿h除啊,所以 d 后面通常不接任何咚咚;
i :插入, i 的后面可以接字符串,而這些字符串會(huì)在新的一行出現(xiàn)(目前的上一行);
p :打印,亦即將某個(gè)選擇的數(shù)據(jù)印出。通常 p 會(huì)與參數(shù) sed -n 一起運(yùn)作~
s :取代,可以直接進(jìn)行取代的工作哩!通常這個(gè) s 的動(dòng)作可以搭配
正規(guī)表示法!例如 1,20s/old/new/g 就是啦!
范例:
范例一:將 /etc/passwd 的內(nèi)容列出,并且我需要打印行號(hào),同時(shí),請(qǐng)將第 2~5 行刪除!
[root@linux ~]# nl /etc/passwd |sed '2,5d'
1 root:x:0:0:root:/root:/bin/bash
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
.....(后面省略).....
# 看到了吧?因?yàn)?2-5 行給他刪除了,所以顯示的數(shù)據(jù)中,就沒(méi)有 2-5 行啰~
# 另外,注意一下,原本應(yīng)該是要下達(dá) sed -e 才對(duì),沒(méi)有 -e 也行啦!
# 同時(shí)也要注意的是, sed 后面接的動(dòng)作,請(qǐng)務(wù)必以 '' 兩個(gè)單引號(hào)括住喔!
# 而,如果只要?jiǎng)h除第 2 行,可以使用 nl /etc/passwd | sed '2d' 來(lái)達(dá)成,
# 至于第 3 到最后一行,則是 nl /etc/passwd | sed '3,$d' 的啦!
范例二:承上題,在第二行后(亦即是加在第三行)加上『drink tea?』字樣!
[root@linux ~]# nl /etc/passwd |sed '2a drink tea'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
drink tea
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
# 嘿嘿!在 a 后面加上的字符串就已將出現(xiàn)在第二行后面啰!那如果是要在第二行前呢?
# nl /etc/passwd | sed '2i drink tea' 就對(duì)啦!
范例三:在第二行后面加入兩行字,例如『Drink tea or .....』『drink beer?』
[root@linux ~]# nl /etc/passwd | sed '2a Drink tea or ......\
> drink beer ?'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
Drink tea or ......
drink beer ?
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
# 這個(gè)范例的重點(diǎn)是,我們可以新增不只一行喔!可以新增好幾行~
# 但是每一行之間都必須要以反斜線 \ 來(lái)進(jìn)行新行的增加喔!所以,上面的例子中,
# 我們可以發(fā)現(xiàn)在第一行的最后面就有 \ 存在啦!那是一定要的喔!
范例四:我想將第2-5行的內(nèi)容取代成為『No 2-5 number』呢?
[root@linux ~]# nl /etc/passwd | sed '2,5c No 2-5 number'
1 root:x:0:0:root:/root:/bin/bash
No 2-5 number
6 sync:x:5:0:sync:/sbin:/bin/sync
# 沒(méi)有了 2-5 行,嘿嘿嘿嘿!我們要的數(shù)據(jù)就出現(xiàn)啦!
范例五:僅列出第 5-7 行
[root@linux ~]# nl /etc/passwd | sed -n '5,7p'
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
# 為什么要加 -n 的參數(shù)呢?您可以自行下達(dá) sed '5,7p' 就知道了!(5-7行會(huì)重復(fù)輸出)
# 有沒(méi)有加上 -n 的參數(shù)時(shí),輸出的數(shù)據(jù)可是差很多的喔!
范例六:我們可以使用 ifconfig 來(lái)列出 IP ,若僅要 eth0 的 IP 時(shí)?
[root@linux ~]# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:51:FD:52:9A:CA
inet addr:192.168.1.12 Bcast:192.168.1.255
Mask:255.255.255.0
inet6 addr: fe80::250:fcff:fe22:9acb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
.....(以下省略).....
# 其實(shí),我們要的只是那個(gè) inet addr:..那一行而已,所以啰,利用 grep 與 sed 來(lái)捉
[root@linux ~]# ifconfig eth0 | grep 'inet ' | sed 's/^.*addr://g' |
\
> sed 's/Bcast.*$//g'
# 您可以將每個(gè)管線 (|) 的過(guò)程都分開(kāi)來(lái)執(zhí)行,就會(huì)曉得原因啰!
# 去頭去尾之后,就會(huì)得到我們所需要的 IP 亦即是 192.168.1.12 啰~
范例七:將 /etc/man.config 檔案的內(nèi)容中,有 MAN 的設(shè)定就取出來(lái),但不要說(shuō)明內(nèi)容。
[root@linux ~]# cat /etc/man.config | grep 'MAN'| sed 's/#.*$//g' |
\
> sed '/^$/d'
# 每一行當(dāng)中,若有 # 表示該行為批注,但是要注意的是,有時(shí)候,
# 批注并不是寫(xiě)在第一個(gè)字符,亦即是寫(xiě)在某個(gè)指令后方,如底下的模樣:
# 『shutdown -h now # 這個(gè)是關(guān)機(jī)的指令』,批注 # 就在指令的后方了。
# 因此,我們才會(huì)使用到將 #.*$ 這個(gè)正規(guī)表示法!
范例八:利用 sed 直接在 ~/.bashrc 最后一行加入『# This is a test』
[root@linux ~]# sed -i '$a # This is a test' ~/.bashrc
# 上頭的 -i 參數(shù)可以讓你的 sed 直接去修改后面接的檔案內(nèi)容喔!而不是由屏幕輸出。
# 至于那個(gè) $a 則代表最后一行才新增的意思。
總之,這個(gè) sed 不錯(cuò)用啦!而且很多的 shell script 都會(huì)使用到這個(gè)指令的功能~ sed
可以幫助系統(tǒng)管理員管理好日常的工作喔!要仔細(xì)的學(xué)習(xí)呢!
awk 工具簡(jiǎn)介
相較于 sed 常常作用于一整個(gè)行的處理, awk 則比較傾向于一行當(dāng)中分成數(shù)個(gè)『字段』來(lái)處理。 因此,awk
相當(dāng)?shù)倪m合處理小型的數(shù)據(jù)數(shù)據(jù)處理呢!awk 通常運(yùn)作的模式是這樣的:
[root@linux ~]# awk '條件類型1{動(dòng)作1} 條件類型2{動(dòng)作2} ...' filename awk
可以處理后續(xù)接的檔案,也可以讀取來(lái)自前個(gè)指令的 standard output 。 但如前面說(shuō)的, awk
主要是處理『每一行的字段內(nèi)的數(shù)據(jù)』,而預(yù)設(shè)的『字段的分隔符為 "空格鍵" 或 "[tab]鍵" 』!舉例來(lái)說(shuō),我們用 last
可以將登入者的數(shù)據(jù)取出來(lái), 結(jié)果如下所示:
[root@linux ~]#lastdmtsai pts/0 192.168.1.12 Mon Aug 22
09:40 still logged in
root tty1 Mon Aug 15 11:38 - 11:39
(00:01)
reboot system boot 2.6.11 Sun Aug 14 18:18
(7+15:41)
dmtsai pts/0 192.168.1.12 Fri Aug 12 12:07 - 12:08
(00:01)
若我想要取出賬號(hào)與登入者的 IP ,且賬號(hào)與 IP 之間以 [tab] 隔開(kāi),則會(huì)變成這樣:
[root@linux ~]# last | awk '{print $1 "\t" $3}'
dmtsai 192.168.1.12
root Mon
reboot boot
dmtsai 192.168.1.12
因?yàn)椴徽撃囊恍形叶家幚?,因此,就不需要?"條件類型" 的限制!我所想要的是第一欄以及第三欄,
但是,第二行及第三行的內(nèi)容怪怪的~這是因?yàn)閿?shù)據(jù)格式的問(wèn)題??!所以啰~使用 awk
的時(shí)候,請(qǐng)先確認(rèn)一下您的數(shù)據(jù)當(dāng)中,如果是連續(xù)性的數(shù)據(jù),請(qǐng)不要有空格或 [tab] 在內(nèi),否則,就會(huì)像這個(gè)例子這樣,會(huì)發(fā)生誤判喔!
另外,由上面這個(gè)例子您也會(huì)知道,在每一行的每個(gè)字段都是有變量名稱的,那就是 $1, $2... 等變量名稱,以上面的例子來(lái)說(shuō),
dmtsai 是 $1 ,因?yàn)樗堑谝粰诼铮≈劣?192.168.1.12 是第三欄, 所以他就是 $3
啦!后面以此類推~呵呵!還有個(gè)變數(shù)喔!那就是 $0 ,$0 代表『一整列資料』的意思~ 以上面的例子來(lái)說(shuō),第一行的 $0
代表的就是『dmtsai pts/0.... 』那一行??! 由此可知,剛剛上面四行當(dāng)中,整個(gè) awk 的處理流程是:
讀入第一行,并將第一行的資料填入 $0, $1, $2.... 等變數(shù)當(dāng)中;
依據(jù) "條件類型" 的限制,判斷是否需要進(jìn)行后面的 "動(dòng)作";
做完所有的動(dòng)作與條件類型;
若還有后續(xù)的『行』的數(shù)據(jù),則重復(fù)上面 1~3 的步驟,直到所有的數(shù)據(jù)都讀完為止。經(jīng)過(guò)這樣的步驟,您會(huì)曉得, awk
是『以行為一次處理的單位』, 而『以字段為最小的處理單位』。好了,那么 awk 怎么知道我到底這個(gè)數(shù)據(jù)有幾行?有幾欄呢?這就需要 awk
的內(nèi)建變量的幫忙啦~
變量名稱
代表意義
NF
每一行 ($0) 擁有的字段總數(shù)
NR
目前 awk 所處理的是『第幾行』數(shù)據(jù)
FS
目前的分隔字符,預(yù)設(shè)是空格鍵
我們繼續(xù)以上面例子來(lái)做說(shuō)明,如果我想要列出每一行的賬號(hào),并且列出目前處理的行數(shù), 并且說(shuō)明,該行有多少字段,則可以這樣 (注意, awk
后續(xù)的所有動(dòng)作以 ' 括住, 所以,內(nèi)容如果想要以 print 打印時(shí),記得,非變量的文字部分,包含上一小節(jié)
printf
提到的格式中,都需要使用雙引號(hào)來(lái)定義出來(lái)喔!)
[root@linux ~]# last | awk '{print $1 "\t lines: " NR "\t columes: "
NF}'
dmtsai lines: 1 columes: 10
root lines: 2 columes: 9
reboot lines: 3 columes: 9
dmtsai lines: 4 columes: 10
這樣可以了解 NR 與 NF 的差別了吧?好了,底下來(lái)談一談所謂的 "條件類型" 了吧!
awk 的邏輯運(yùn)算字符
既然有需要用到 "條件" 的類別,自然就需要一些邏輯運(yùn)算啰~例如底下這些:
運(yùn)算單元
代表意義
>
大于
小于
>=
大于或等于
小于或等于
==
等于
!=
不等于
值得注意的是那個(gè) == 的符號(hào),因?yàn)樵凇哼壿嬤\(yùn)算』上面, 就是所謂的大于、小于、等于等等的判斷式上面,我們習(xí)慣上是以 ==
來(lái)表示,而如果是直接給予一個(gè)值,例如變量設(shè)定時(shí),就直接使用 = 而已。 好了,我們實(shí)際來(lái)運(yùn)用一下邏輯判斷吧!舉例來(lái)說(shuō),在
/etc/passwd 當(dāng)中是以冒號(hào) ":" 來(lái)作為字段的分隔,那假設(shè)我要查閱,第三欄小于 10 以下的數(shù)據(jù),并且僅列出賬號(hào)與第三欄,
那么可以這樣做:
[root@linux ~]# cat /etc/passwd | \
> awk '{FS=":"} $3
root:x:0:0:root:/root:/bin/bash
bin 1
daemon 2
......(以下省略)......
有趣吧!不過(guò),怎么第一行沒(méi)有正確的顯示出來(lái)呢?這是因?yàn)槲覀冏x入第一行的時(shí)候, 那些變數(shù) $1, $2...
預(yù)設(shè)還是以空格鍵為分隔的,所以雖然我們定義了 FS=":" 了, 但是卻僅能在第二行后才開(kāi)始生效。那么怎么辦呢?我們可以預(yù)先設(shè)定 awk
的變量??! 利用 BEGIN 這個(gè)關(guān)鍵詞喔!這樣做:
[root@linux ~]# cat /etc/passwd | \
> awk 'BEGIN {FS=":"} $3 ......(以下省略)......
很有趣吧!而除了 BEGIN 之外,我們還有 END 呢!另外,如果要用 awk 來(lái)進(jìn)行『計(jì)算功能』呢?以底下的例子來(lái)看,
假設(shè)我有一個(gè)薪資數(shù)據(jù)表,內(nèi)容是這樣的:
Name 1st 2nd 3th
VBird 23000 24000 25000
DMTsai 21000 20000 23000
Bird2 43000 42000 41000
如何幫我計(jì)算每個(gè)人的總額呢?而且我還想要格式化輸出喔! 你可以將上面的數(shù)據(jù)儲(chǔ)存成一個(gè)名稱為 pay.txt 的檔案,則:
[root@linux ~]# cat pay.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 %10d %10.2f\n", $1, $2, $3, $4, total}'
Name 1st 2nd 3th Total
VBird 23000 24000 25000 72000.00
DMTsai 21000 20000 23000 64000.00
Bird2 43000 42000 41000 126000.00
上面的例子有幾個(gè)重要事項(xiàng)應(yīng)該要先說(shuō)明的:
所有的動(dòng)作,亦即在 {} 內(nèi)的動(dòng)作,如果有需要多個(gè)指令輔助時(shí),可利用分號(hào)『;』間隔, 或者直接以 [Enter]
按鍵來(lái)隔開(kāi)每個(gè)指令,例如上面的 NR>=2 后面接的動(dòng)作, 利用 total = ... 那個(gè)指令來(lái)指定加總,而后續(xù)則以
printf 來(lái)格式化輸出!
邏輯運(yùn)算當(dāng)中,如果是『等于』的情況,則務(wù)必使用兩個(gè)等號(hào)『==』!
格式化輸出時(shí),在 printf 的格式設(shè)定當(dāng)中,務(wù)必加上 \n ,才能進(jìn)行分行!
與 bash shell 的變量不同,在 awk 當(dāng)中,變量可以直接使用,不需加上 $ 符號(hào)。
利用 awk 這個(gè)玩意兒,就可以幫我們處理很多日常工作了呢!真是好用的很~ 此外, awk 的輸出格式當(dāng)中,常常會(huì)以
printf
來(lái)輔助,所以, 最好您對(duì) printf 也稍微熟悉一下比較好啦!另外, awk 的動(dòng)作內(nèi) {} 也是支持 if (條件) 的喔!
舉例來(lái)說(shuō),上面的指令可以修訂成為這樣的
[root@linux ~]# cat pay.txt | \
> awk '{if(NR==1) printf "%10s %10s %10s %10s
%10s\n",$1,$2,$3,$4,"Total"}
NR>=2{total = $2 + $3 + $4
printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'
你可以仔細(xì)的比對(duì)一下上面兩個(gè)輸入有啥不同~從中去了解兩種語(yǔ)法吧! 我個(gè)人是比較傾向于使用第一種語(yǔ)法,因?yàn)闀?huì)比較有統(tǒng)一性??! ^_^
上述就是小編為大家分享的sed&awk的基本使用方法是什么了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。