杭州Linux運(yùn)維哪家好?
Tips:
當(dāng)你**次拿起雙手在電腦上使用 awk 命令處理一個(gè)或者多個(gè)文件的時(shí)候,它會(huì)依次讀取文件的每一行內(nèi)容, 然后對(duì)其進(jìn)行處理,awk 命令默認(rèn)從 stdio 標(biāo)準(zhǔn)輸入獲取文件內(nèi)容, awk 使用一對(duì)單引號(hào)來表示 一些可執(zhí)行的腳本代碼,在可執(zhí)行腳本代碼里面,使用一對(duì)花括號(hào)來表示一段可執(zhí)行代碼塊,可以同時(shí)存在多個(gè)代碼塊。 awk 的每個(gè)花括號(hào)內(nèi)同時(shí)又可以有多個(gè)指令,每一個(gè)指令用分號(hào)分隔,awk 其實(shí)就是一個(gè)腳本編程語言。說了這么多,你肯定還是一臉的懵逼。先別急,往下看。。。
awk [options] 'program' file
options 這個(gè)表示一些可選的參數(shù)選項(xiàng),反正就是你愛用不用,不用可以拉到。。。 program 這個(gè)表示 awk 的可執(zhí)行腳本代碼,這個(gè)是必須要有的。 file 這個(gè)表示 awk 需要處理的文件,注意是純文本文件,不是你的 mp3,也不是 mp4 啥的。。
$ awk '{print $0}' /etc/passwd
awk 命令的可執(zhí)行腳本代碼使用單引號(hào)括起來,緊接著里面是一對(duì)花括號(hào),記住是 "花括號(hào)" 不是 "花姑娘",然后花括號(hào)里面就是一些可執(zhí)行的腳本代碼段,當(dāng) awk 每讀取一行之后,它會(huì)依次執(zhí)行雙引號(hào)里面的每個(gè)腳本代碼段,在上面這個(gè)例子中, $0 表示當(dāng)前行。當(dāng)你執(zhí)行了上面的命令之后,它會(huì)依次將 /etc/passwd 文件的每一行內(nèi)容打印輸出。
awk 默認(rèn)的分割符為空格和制表符,我們可以使用 -F 參數(shù)來指定分隔符
$ awk -F ':' '{print $1}' /etc/passwdrootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobody
上面的命令將 /etc/passwd 文件中的每一行用冒號(hào) : 分割成多個(gè)字段,然后用 print 將第 1 列字段的內(nèi)容打印輸出
比如現(xiàn)在有這樣一個(gè)文件 some.log 文件內(nèi)容如下
Grape(100g)1980raisins(500g)1990plum(240g)1997apricot(180g)2005nectarine(200g)2008
現(xiàn)在我們想將上面的 some.log 文件中按照 "水果名稱(重量)年份" 來進(jìn)行分割
$ awk -F '[()]' '{print $1, $2, $3}' some.logGrape 100g 1980raisins 500g 1990plum 240g 1997apricot 180g 2005nectarine 200g 2008
在 -F 參數(shù)中使用一對(duì)方括號(hào)來指定多個(gè)分隔符,awk 處理 some.log 文件時(shí)就會(huì)使用 "(" 和 ")" 來對(duì)文件的每一行進(jìn)行分割。
$0 這個(gè)表示文本處理時(shí)的當(dāng)前行
$1 表示文本行被分隔后的第 1 個(gè)字段列
$2 表示文本行被分割后的第 2 個(gè)字段列
$3 表示文本行被分割后的第 3 個(gè)字段列
$n 表示文本行被分割后的第 n 個(gè)字段列
NR 表示文件中的行號(hào),表示當(dāng)前是第幾行
NF 表示文件中的當(dāng)前行列的個(gè)數(shù),類似于 mysql 數(shù)據(jù)表里面每一條記錄有多少個(gè)字段
FS 表示 awk 的輸入分隔符,默認(rèn)分隔符為空格和制表符,你可以對(duì)其進(jìn)行自定義設(shè)置
OFS 表示 awk 的輸出分隔符,默認(rèn)為空格,你也可以對(duì)其進(jìn)行自定義設(shè)置
FILENAME 表示當(dāng)前文件的文件名稱,如果同時(shí)處理多個(gè)文件,它也表示當(dāng)前文件名稱
比如我們有這么一個(gè)文本文件 fruit.txt 內(nèi)容如下,我將用它來向你演示如何使用 awk 命令工具,順便活躍一下此時(shí)尷尬的氣氛。。
peach 100 Mar 1997 ChinaLemon 150 Jan 1986 AmericaPear 240 Mar 1990 Janpanavocado 120 Feb 2008 china
我們來瞧一瞧下面這些簡(jiǎn)單到爆炸的例子,這個(gè)表示打印輸出文件的每一整行的內(nèi)容
$ awk '{print $0}' fruit.txtpeach 100 Mar 1997 ChinaLemon 150 Jan 1986 AmericaPear 240 Mar 1990 Janpanavocado 120 Feb 2008 china
下面這個(gè)表示打印輸出文件的每一行的第 1 列內(nèi)容
$ awk '{print $1}' fruit.txtpeachLemonPearavocado
下面面這個(gè)表示打印輸出文件的每一行的第 1 列、第 2 列和第 3 列內(nèi)容
$ awk '{print $1, $2, $3}' fruit.txtpeach 100 MarLemon 150 JanPear 240 Maravocado 120 Feb
其中加入的逗號(hào)表示插入輸出分隔符,也就是默認(rèn)的空格
文件的每一行的每一列的內(nèi)容除了可以用 print 命令打印輸出以外,還可以對(duì)其進(jìn)行賦值
$ awk '{$2 = "***"; print $0}' fruit.txtpeach *** Mar 1997 ChinaLemon *** Jan 1986 AmericaPear *** Mar 1990 Janpanavocado *** Feb 2008 china
上面的例子就是表示**對(duì) $2 變量進(jìn)行重新賦值,來隱藏每一行的第 2 列內(nèi)容,并且用星號(hào) * 來代替其輸出
在參數(shù)列表中加入一些字符串或者轉(zhuǎn)義字符之類的東東
$ awk '{print $1 "\t" $2 "\t" $3}' fruit.txtpeach 100 MarLemon 150 JanPear 240 Maravocado 120 Feb
像上面這樣,你可以在 print的參數(shù)列表中加入一些字符串或者轉(zhuǎn)義字符之類的東東,讓輸出的內(nèi)容格式更漂亮,但一定要記住要使用雙引號(hào)。
awk 內(nèi)置 NR 變量表示每一行的行號(hào)
$ awk '{print NR "\t" $0}' fruit.txt1 peach 100 Mar 1997 China2 Lemon 150 Jan 1986 America3 Pear 240 Mar 1990 Janpan4 avocado 120 Feb 2008 china
awk 內(nèi)置 NF 變量表示每一行的列數(shù)
$ awk '{print NF "\t" $0}' fruit.txt5 peach 100 Mar 1997 China5 Lemon 150 Jan 1986 America5 Pear 240 Mar 1990 Janpan5 avocado 120 Feb 2008 china
$ awk '{print $NF}' fruit.txtChinaAmericaJanpanchina
上面這個(gè) $NF 就表示每一行的**后一列,因?yàn)?NF 表示一行的總列數(shù),在這個(gè)文件里表示有 5 列,然后在其前面加上 $ 符號(hào),就變成了 $5 ,表示第 5 列
$ awk '{print $(NF - 1)}' fruit.txt1997198619902008
上面 $(NF-1) 表示倒數(shù)第 2 列, $(NF-2) 表示倒數(shù)第 3 列,依次類推。
現(xiàn)在除了剛才說的有一個(gè) fruit.txt 文件之外,我們又多了一個(gè)新文件叫 company.txt 內(nèi)容如下
yahoo 100 4500google 150 7500apple 180 8000twitter 120 5000
我們用 fruit.txt 和 company.txt 兩個(gè)文件來向你演示 awk 同時(shí)處理多個(gè)文件的時(shí)候有什么效果
$ awk '{print FILENAME "\t" $0}' fruit.txt company.txtfruit.txt peach 100 Mar 1997 Chinafruit.txt Lemon 150 Jan 1986 Americafruit.txt Pear 240 Mar 1990 Janpanfruit.txt avocado 120 Feb 2008 chinacompany.txt yahoo 100 4500company.txt google 150 7500company.txt apple 180 8000company.txt twitter 120 5000
當(dāng)你使用 awk 同時(shí)處理多個(gè)文件的時(shí)候,它會(huì)將多個(gè)文件合并處理,變量 FILENAME 就表示當(dāng)前文本行所在的文件名稱。
看到這里是不是感覺 awk 命令的使用方法真的是簡(jiǎn)單到爆炸,現(xiàn)在不要太高興,請(qǐng)舉起你的雙手跟我一起搖擺。。。哦,不對(duì)!請(qǐng)拿起你的雙手在電腦上試一試上面這些例子。
在腳本代碼段前面使用 BEGIN 關(guān)鍵字時(shí),它會(huì)在開始讀取一個(gè)文件之前,運(yùn)行一次 BEGIN 關(guān)鍵字后面的腳本代碼段, BEGIN 后面的腳本代碼段只會(huì)執(zhí)行一次,執(zhí)行完之后 awk 程序就會(huì)退出
$ awk 'BEGIN {print "Start read file"}' /etc/passwdStart read file
awk 腳本中可以用多個(gè)花括號(hào)來執(zhí)行多個(gè)腳本代碼,就像下面這樣
$ awk 'BEGIN {print "Start read file"} {print $0}' /etc/passwdStart read fileroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody:x:99:99:Nobody:/:/sbin/nologin
awk 的 END 指令和 BEGIN 恰好相反,在 awk 讀取并且處理完文件的所有內(nèi)容行之后,才會(huì)執(zhí)行 END 后面的腳本代碼段
$ awk 'END {print "End file"}' /etc/passwdEnd file
一定要多動(dòng)手在電腦上敲一敲這些命令,對(duì)身體好。腦子是個(gè)好東西,要多用。。。
$ awk 'BEGIN {print "Start read file"} {print $0} END {print "End file"}' /etc/passwdStart read fileroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody:x:99:99:Nobody:/:/sbin/nologinEnd file
可以在 awk 腳本中聲明和使用變量
$ awk '{msg="hello world"; print msg}' /etc/passwdhello worldhello worldhello worldhello worldhello world
awk 聲明的變量可以在任何多個(gè)花括號(hào)腳本中使用
$ awk 'BEGIN {msg="hello world"} {print msg}' /etc/passwdhello worldhello worldhello worldhello worldhello world
在 awk 中,像其他編程語言一樣,它也支持一些基本的數(shù)學(xué)運(yùn)算操作
$ awk '{a = 12; b = 24; print a b}' company.txt36363636
上面這段腳本表示,先聲明兩個(gè)變量 a = 12 和 b = 24,然后用 print 打印出 a 加上 b 的結(jié)果。
看到上面的輸出結(jié)果,你很可能又是一臉的懵逼,為什么會(huì)重復(fù)輸出 4 次同樣的計(jì)算結(jié)果。所以說小時(shí)不學(xué)好,長(zhǎng)大做IT。 知識(shí)這東西真到了要用的時(shí)候,能亮瞎別人的雙眼,好了,不廢話。請(qǐng)記住 awk 是針對(duì)文件的每一行來執(zhí)行一次單引號(hào) 里面的腳本代碼,每讀取到一行就會(huì)執(zhí)行一次,文件里面有多少行就會(huì)執(zhí)行多少次,但 BEGIN 和 END 關(guān)鍵字后面的 腳本代碼除外,如果被處理的文件中什么都沒有,那 awk 就一次都不會(huì)執(zhí)行。。。
加法運(yùn)算符
- 減法運(yùn)算符
* 乘法運(yùn)算符
/ 除法運(yùn)算符
% 取余運(yùn)算符
比如有一個(gè)文件 company.txt 內(nèi)容如下
yahoo 100 4500google 150 7500apple 180 8000twitter 120 5000
我們要判斷文件的第 3 列數(shù)據(jù),也就是平均工資小于 5500 的公司,然后將其打印輸出
$ awk '$3 < 5500 {print $0}' company.txtyahoo 100 4500twitter 120 5000
上面的命令結(jié)果就是平均工資小于 5500 的公司名單, $3 < 5500 表示當(dāng)?shù)?3 列字段的內(nèi)容小于 5500 的時(shí)候才會(huì)執(zhí)行后面的 {print $0} 代碼塊
$ awk '$1 == "yahoo" {print $0}' company.txtyahoo 100 4500
< 小于
<= 小于或等于
== 等于
!= 不等于
> 大于
>= 大于或等于
~ 匹配正則表達(dá)式
!~ 不匹配正則表達(dá)式
使用 if 指令判斷來實(shí)現(xiàn)上面同樣的效果
$ awk '{if ($3 < 5500) print $0}' company.txtyahoo 100 4500twitter 120 5000
上面表示如果第 3 列字段小于 5500 的時(shí)候就會(huì)執(zhí)行后面的 print $0,很像 C 語言和 PHP 的語法對(duì)不對(duì)。
在 awk 中支持正則表達(dá)式的使用,如果你還對(duì)正則表達(dá)式不是很了解,請(qǐng)先停下來,上 google 去搜一下。
比如現(xiàn)在我們有這么一個(gè)文件 poetry.txt 里面都是我寫的詩,不要問我為什么那么的有才華。內(nèi)容如下:
This above all: to thine self be trueThere is nothing either good or bad, but thinking makes it soThere’s a special providence in the fall of a sparrowNo matter how dark long, may eventually in the day arrival
使用正則表達(dá)式匹配字符串 "There" ,將包含這個(gè)字符串的行打印并輸出
$ awk '/There/{print $0}' poetry.txtThere is nothing either good or bad, but thinking makes it soThere’s a special providence in the fall of a sparrow
使用正則表達(dá)式配一個(gè)包含字母 t 和字母 e ,并且 t 和 e 中間只能有任意單個(gè)字符的行
$ awk '/t.e/{print $0}' poetry.txtThere is nothing either good or bad, but thinking makes it soThere’s a special providence in the fall of a sparrowNo matter how dark long, may eventually in the day arrival
如果只想匹配單純的字符串 "t.e", 那正則表達(dá)式就是這樣的 /t\.e/ ,用反斜杠來轉(zhuǎn)義 . 符號(hào) 因?yàn)?nbsp;. 在正則表達(dá)式里面表示任意單個(gè)字符。
使用正則表達(dá)式來匹配所有以 "The" 字符串開頭的行
$ awk '/^The/{print $0}' poetry.txtThere is nothing either good or bad, but thinking makes it soThere’s a special providence in the fall of a sparrow
在正則表達(dá)式中 ^ 表示以某某字符或者字符串開頭。
使用正則表達(dá)式來匹配所有以 "true" 字符串結(jié)尾的行
$ awk '/true$/{print $0}' poetry.txtThis above all: to thine self be true
在正則表達(dá)式中 $ 表示以某某字符或者字符串結(jié)尾。
又一個(gè)正則表達(dá)式例子如下
$ awk '/m[a]t/{print $0}' poetry.txtNo matter how dark long, may eventually in the day arrival
上面這個(gè)正則表達(dá)式 /m[a]t/ 表示匹配包含字符 m ,然后接著后面還要包含中間方括號(hào)中表示的單個(gè)字符 a ,**后還要包含字符 t 的行,輸出結(jié)果中只有單詞 "matter" 符合這個(gè)正則表達(dá)式的匹配。因?yàn)檎齽t表達(dá)式 [a] 方括號(hào)中表示匹配里面的任意單個(gè)字符。
繼續(xù)上面的一個(gè)新例子如下
$ awk '/^Th[ie]/{print $0}' poetry.txtThis above all: to thine self be trueThere is nothing either good or bad, but thinking makes it soThere’s a special providence in the fall of a sparrow
這個(gè)例子中的正則表達(dá)式 /^Th[ie]/表示匹配以字符串 "Thi" 或者 "The" 開頭的行,正則表達(dá)式方括號(hào)中表示匹配其中的任意單個(gè)字符。
再繼續(xù)上面的新的用法
$ awk '/s[a-z]/{print $0}' poetry.txtThis above all: to thine self be trueThere is nothing either good or bad, but thinking makes it soThere’s a special providence in the fall of a sparrow
正則表達(dá)式 /s[a-z]/ 表示匹配包含字符 s 然后后面跟著任意 a 到 z 之間的單個(gè)字符的字符串,比如 "se", "so", "sp" 等等。
正則表達(dá)式 [] 方括號(hào)中還有一些其他用法比如下面這些
[a-zA-Z] 表示匹配小寫的 a 到 z 之間的單個(gè)字符,或者大寫的 A 到 Z 之間的單個(gè)字符[^a-z] 符號(hào) `^` 在方括號(hào)里面表示取反,也就是非的意思,表示匹配任何非 a 到 z 之間的單個(gè)字符
正則表達(dá)式中的星號(hào) * 和加號(hào) 的使用方法
$ awk '/go*d/{print $0}' poetry.txtThere is nothing either good or bad, but thinking makes it so
上面這個(gè)表示匹配包含字符串 "god",并且中間的字母 "o" 可以出現(xiàn) 0 次或者多次,比如單詞 "good" 就符合這個(gè)要求。 正則表達(dá)式中的 和星號(hào)原理差不多,只是加號(hào)表示任意 1 個(gè)或者 1 個(gè)以上,也就是必須至少要出現(xiàn)一次。
正則表達(dá)式問號(hào) ? 的使用方法
$ awk '/ba?d/{print $0}' poetry.txtThere is nothing either good or bad, but thinking makes it so
正則表達(dá)式中的問號(hào) ? 表示它前面的字符只能出現(xiàn) 0 次 或者 1 次,也就是可以不出現(xiàn),也可以出現(xiàn),但如果有出現(xiàn)也只能出現(xiàn) 1 次。
正則表達(dá)式中的 {} 花括號(hào)用法
$ awk '/go{2}d/{print $0}' poetry.txtThere is nothing either good or bad, but thinking makes it so
花括號(hào) {} 表示規(guī)定它前面的字符必須出現(xiàn)的次數(shù),像上面這個(gè) /go{2}d/ 就表示只匹配字符串 "good",也就是中間的字母 "o" 必須要出現(xiàn) 2 次。
正則表達(dá)式中的花括號(hào)還有一些其他的用法如下
/go{2,3}d/ 表示字母 "o" 只能可以出現(xiàn) 2 次或者 3 次/go{2,10}d/ 表示字母 "o" 只能可以出現(xiàn) 2次,3次,4次,5次,6次 ... 一直到 10 次/go{2,}d/ 表示字母 "o" 必須至少出現(xiàn) 2 次或著 2 次以上
正則表達(dá)式中的圓括號(hào)的用法
$ awk '/th(in){1}king/{print $0}' poetry.txtThere is nothing either good or bad, but thinking makes it so
正則表達(dá)式中的圓括號(hào)表示將多個(gè)字符當(dāng)成一個(gè)完整的對(duì)象來看待。比如 /th(in){1}king/ 就表示其中字符串 "in" 必須出現(xiàn) 1 次。而如果不加圓括號(hào)就變成了 /thin{1}king/ 這個(gè)就表示其中字符 "n" 必須出現(xiàn) 1 次。
看到這里,如果你對(duì) poetry.txt 件中寫的詩比較熟悉,你就會(huì)發(fā)現(xiàn)。。。我去!這詩根本就不是我寫的。所以論多讀書是多么的重要。我有幸借用莎士比亞的詩來向你講解如何在 awk 中使用正則表達(dá)式。
因?yàn)?awk 算起來也是一種編程語言,它的功能遠(yuǎn)遠(yuǎn)不止我們上面講的這些,awk 還有一些其他比較復(fù)雜的功能。但一般我們不建議將 awk 用的太過于復(fù)雜。通常面對(duì)一些比較復(fù)雜的場(chǎng)景我們還是要使用其他的一些工具,比如 shell 腳本,Lua 等等
咨詢電話【詹老師】:17706505315
了解更多的杭州Linux認(rèn)證課程>>>>杭州Linux認(rèn)證培訓(xùn)
了解更多的杭州培訓(xùn)課程>>>>杭州培訓(xùn)網(wǎng)