Shell腳本之a(chǎn)wk詳解

一.基本介紹

1.awk:

awk是一個(gè)強(qiáng)大的文本分析工具,在對(duì)文本文件的處理以及生成報(bào)表,awk是無可替代的。awk認(rèn)為文本文件都是結(jié)構(gòu)化的,它將每一個(gè)輸入行定義為一個(gè)記錄,行中的每個(gè)字符串定義為一個(gè)域(段),域和域之間使用分割符分割。

2.功能:流控制、數(shù)學(xué)運(yùn)算、進(jìn)程控制、內(nèi)置的變量和函數(shù)、循環(huán)和判斷

3.工作原理:

awk 會(huì)把每行進(jìn)行一個(gè)拆分,用相應(yīng)的命令對(duì)拆分出來的“段”進(jìn)行處理。

(1)行工作模式,讀入文件的每一行,會(huì)把一行的內(nèi)容,存到$0里

(2)使用內(nèi)置的變量FS(段的分隔符,默認(rèn)用的是空白字符),分割這一行,把分割出來的每個(gè)段存到相應(yīng)的變量$(1-100)

(3)輸出的時(shí)候按照內(nèi)置變量OFS(out FS),輸出

(4)讀入下一行繼續(xù)操作

簡單實(shí)例

[root@tx3 ~]# echo "this is a book" > awk.txt

[root@tx3 ~]# awk '{print $2,$1,$3,$4}' awk.txt

is this a book

4. ? Awk常用內(nèi)置變量表:

1 $0 ? ? ? ? ? ? 當(dāng)前記錄(作為單個(gè)變量)

2 $1~$n ? ? ? ? ?當(dāng)前記錄的第n個(gè)字段,字段間由FS分隔

3 FS ? ? ? ? ? ? 輸入字段分隔符 默認(rèn)是空格

4 NF ? ? ? ? ? ? 當(dāng)前記錄中的字段個(gè)數(shù),就是有多少列

5 NR ? ? ? ? ? ? 已經(jīng)讀出的記錄數(shù),就是行號(hào),從1開始

6 RS ? ? ? ? ? ? 輸入的記錄他隔符默 認(rèn)為換行符

7 OFS ? ? ? ? ? ?輸出字段分隔符 默認(rèn)也是空格

8 ORS ? ? ? ? ? ?輸出的記錄分隔符,默認(rèn)為換行符

9 ARGC ? ? ? ? ? 命令行參數(shù)個(gè)數(shù)

10 ARGV ? ? ? ? ? 命令行參數(shù)數(shù)組

11 FILENAME ? ? ? 當(dāng)前輸入文件的名字

12 IGNORECASE ? ? 如果為真,則進(jìn)行忽略大小寫的匹配

13 ARGIND ? ? ? ? 當(dāng)前被處理文件的ARGV標(biāo)志符

14 CONVFMT ? ? ? ?數(shù)字轉(zhuǎn)換格式 %.6g

15 ENVIRON ? ? ? ?UNIX環(huán)境變量

16 ERRNO ? ? ? ? ?UNIX系統(tǒng)錯(cuò)誤消息

17 FIELDWIDTHS ? ?輸入字段寬度的空白分隔字符串

18 FNR ? ? ? ? ? ?當(dāng)前記錄數(shù)

19 OFMT ? ? ? ? ? 數(shù)字的輸出格式 %.6g

20 RSTART ? ? ? ? 被匹配函數(shù)匹配的字符串首

21 RLENGTH ? ? ? ?被匹配函數(shù)匹配的字符串長度

二.print的簡單使用

例:打印整行: $0

[root@tx3 ~]# cp /etc/passwd p1

[root@tx3 ~]# awk '{print $0}' p1

例:打印每行的最后一個(gè)字段: $NF

[root@tx3 ~]# awk -F : '{print $NF}' p1

例:打印第三個(gè)字段: $3

[root@tx3 ~]# awk -F : '{print $3}' p1

例:打印第一行NR==1

[root@tx3 ~]# awk 'NR==1{print $0}' p1

root:x:0:0:root:/root:/bin/bash

例:打印最后一行

[root@tx3 ~]# awk 'END{print $0}' p1

tx:x:500:500:tx:/home/tx:/bin/bash

例:打印第一行最后一個(gè)字段

[root@tx3 ~]# awk -F: 'NR==1{print $NF}' p1

/bin/bash

例:打印最后一行最后一個(gè)字段

[root@tx3 ~]#awk -F: 'END{print $NF}' p1

例:打印每行的倒數(shù)第二個(gè)字段,并在其后打印你好

[root@tx3 ~]# awk -F: '{print $(NF-1),"nihao"}' p1

/root nihao

/bin nihao

/sbin nihao

例:打印行號(hào)

[root@tx3 ~]# awk '{print NR,$0}' p1

1 root:x:0:0:root:/root:/bin/bash

2 bin:x:1:1:bin:/bin:/sbin/nologin

3 daemon:x:2:2:daemon:/sbin:/sbin/nologin

例:打印當(dāng)前系統(tǒng)環(huán)境變量的某個(gè)特定值

[root@tx3 ~]# awk 'BEGIN{print ENVIRON["PATH"];}'

/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

例: 用:分割,刪除第2個(gè)字段

[root@tx3 ~]# awk 'BEGIN{FS=":";OFS=":"}{print $1,$3,$4,$5,$6,$7}' p1

root:0:0:root:/root:/bin/bash

bin:1:1:bin:/bin:/sbin/nologin

daemon:2:2:daemon:/sbin:/sbin/nologin

三.printf的使用

print format 生成報(bào)表

%d ? ? ? ?十進(jìn)制有符號(hào)整數(shù)

%u ? ? ? ?十進(jìn)制無符號(hào)整數(shù)

%f ? ? ? ?浮點(diǎn)數(shù)

%s ? ? ? ?字符串

%c ? ? ? ?顯示字符的ASCII碼

%p ? ? ? ?指針的值

%e ? ? ? ?科學(xué)技術(shù)法顯示數(shù)值

%x ? ? ? ?%X 無符號(hào)以十六進(jìn)制表示的整數(shù)

%o ? ? ? ?無符號(hào)以八進(jìn)制表示的整數(shù)

%g ? ? ? ?%G 以科學(xué)計(jì)數(shù)法或浮點(diǎn)數(shù)的格式顯示數(shù)值

%% ? ? ? ?顯示其自身

修飾符:

-: ?左對(duì)齊

+: ?顯示數(shù)值符號(hào)

N: 顯示

-F 指定段的分隔符

例:(1)生成報(bào)表

例:(2)小數(shù)問題

對(duì)小數(shù)取保留位的時(shí)候,四舍五入

對(duì)小數(shù)取整,不進(jìn)行四舍五入

[root@tx3 ~]# cat awk.1

23.3456 11.234 45.67

[root@tx3 ~]# awk '{printf "%.2f\t%.2f\t%.2f\n",$1,$2,$3}' awk.1

23.3511.2345.67

四.a(chǎn)wk的使用

(1)正則表達(dá)式

\(\) ? \{\} 不支持

. * ^ $ ? + [] | \< \> () ?可以直接使用

例[root@tx3 ~]# awk '/^$/{print "this is an empty line"}' /etc/inittab

this is an empty line

this is an empty line

this is an empty line

this is an empty line

this is an empty line

this is an empty line

this is an empty line

this is an empty line

this is an empty line

例[root@tx3 ~]# awk -F: '/^root/{print $1,$NF}' /etc/passwd

root /bin/bash

例[root@tx3 ~]# awk -F: '!/^root/{print $1,$NF}' /etc/passwd|head -3

bin /sbin/nologin

daemon /sbin/nologin

adm /sbin/nologin

(2)關(guān)系運(yùn)算符

> < == != >= <=

~(匹配) !~(不匹配)

例[root@tx3 ~]# cp /etc/passwd p1

[root@tx3 ~]# awk -F: '$3 == 0 {print $1}' p1

Root

例[root@tx3 ~]# awk -F: '$3 != 0{ print $1}' p1 | head -2

bin

Daemon

例[root@tx3 ~]# awk -F: '$3 < 2 {print $1}' p1

root

bin

(3)邏輯運(yùn)算符

&& || !

與 或 非

例[root@tx3 ~]# awk -F: '$3 > 0 && $3 < 10 {print $1, $3}' p1 |head -2

bin 1

daemon 2

例[root@tx3 ~]# ?awk -F: '$3 > 10 || $3 < 5 {print $1,$3}' p1 |head -6

root 0

bin 1

daemon 2

adm 3

lp 4

operator 11

(4)算數(shù)運(yùn)算符

+ - * / %(取模(余數(shù))) ^(冪運(yùn)算)

例:輸出名字,總成績,平均成績

[root@tx3 ~]# cat cj

tx 90 86 86

tx1 89 78 85

tx2 79 80 85

[root@tx3 ~]# ?awk '{print $1,$2+$3+$4,($2+$3+$4)/3}' cj

tx 262 87.3333

tx1 252 84

tx2 244 81.3333

[root@tx3 ~]# awk '{printf"%-5s %3d %.2f\n",$1,$2+$3+$4,($2+$3+$4)/3}' cj

tx ? ?262 87.33

tx1 ? 252 84.00

tx2 ? 244 81.33

(5)BEGIN ?END

BEGIN{ 動(dòng)作;動(dòng)作;... } ?在處理文件之前,要執(zhí)行的動(dòng)作;只執(zhí)行一次

END{ 動(dòng)作;動(dòng)作;... } ? ?在處理完文件之后,要執(zhí)行的動(dòng)作;只執(zhí)行一次

BEGIN :可以給文件添加標(biāo)題、定義變量、定義文件的分隔符

END:匯總的操作

getline可以從管道和標(biāo)準(zhǔn)輸入讀取輸入,然后傳遞給變量。

例:

[root@tx3 ~]# awk 'BEGIN{"date"| getline a}{print}END{print a}' cj

tx 90 86 86

tx1 89 78 85

tx2 79 80 85

Thu Feb ?7 12:39:25 CST 2013

五.a(chǎn)wk里的流控制和循環(huán)

(1)簡單的條件判斷

語法:(表達(dá)式 ? 值1 : 值2) 如果表達(dá)式成立,輸出值1;否則輸出值2

[root@tx3 ~]# cat num

2 8 9

8 4 6

3 5 7

[root@tx3 ~]# awk '{print ( $1 > $2 ? $1 : $2)}' num

8

8

5

(2)if判斷

語法:

{ if (表達(dá)式

{

動(dòng)作1;動(dòng)作2;...

}

}

如果表達(dá)式成立,那么執(zhí)行動(dòng)作。

[root@tx3 ~]# awk '{if ($2>=80 && $2 <=100) {print $1,"great"} else {print $1, "good"}}' cj

tx great

tx1 great

tx2 good

(2)多支判斷

{

if (表達(dá)式)

{ 動(dòng)作1;動(dòng)作2;...}

else if (表達(dá)式)

{ 動(dòng)作1;動(dòng)作2;...}

else if (表達(dá)式)

{ 動(dòng)作1;動(dòng)作2;...}

......

else

{ 動(dòng)作1;動(dòng)作2;...}

}

[root@tx3 ~]# cat cj

tx 90 86 86

tx1 89 78 85

tx2 79 80 85

tx3 80 70 60

tx4 75 85 65

tx5 78 62 80

判斷的標(biāo)準(zhǔn):

90-100 A

80-89 ?B

70-79 ?C

60-69 ?D

0-59 ? E

[root@tx3 ~]# awk '{ if ($2 >= 90 && $2 <= 100) {print $1,"A"} else if ($2 >= 80 && $2 < 90) {print $1,"B"} else if ($2 >= 70 && $2 < 80) {print $1,"C"} else if ($2 >= 60 && $2 < 70) {print $1,"D"} else {print $1,"E"} }' cj

tx A

tx1 B

tx2 C

tx3 B

tx4 C

tx5 C

(3)循環(huán)while

語法:'var=初值;while (表達(dá)式){動(dòng)作1;...更新變量的動(dòng)作;}'

例:

[root@tx3 ~]# awk -F: '{i=1; while (i<=NF) {print $i;i++}}' p1 | head -7

root

x

0

0

root

/root

/bin/bash

例. 方法一

[root@tx3 ~]# awk -F: '{i=NF; while (i>=2) {printf $i ":";i--};print $1}' p1

/bin/bash:/root:root:0:0:x:root

/sbin/nologin:/bin:bin:1:1:x:bin

/sbin/nologin:/sbin:daemon:2:2:x:daemon

/sbin/nologin:/var/adm:adm:4:3:x:adm

例. 方法二

[root@tx3 ~]# awk 'BEGIN { FS=":" } { i=NF; while (i>=2) {printf $i ":";i--} print $1}' p1

/bin/bash:/root:root:0:0:x:root

/sbin/nologin:/bin:bin:1:1:x:bin

/sbin/nologin:/sbin:daemon:2:2:x:daemon

(4)for循環(huán)

語法:

{

for(表達(dá)式)

{動(dòng)作1;...}

}

表達(dá)式:分為3部分:

(1)初始化表達(dá)式 i=1

(2)測試表達(dá)式 ? i<10

(3)更新測試表達(dá)式 i++

語句:

next 處理輸入行的下一個(gè)輸入行

exit 退出

continue 結(jié)束本次循環(huán)

break 跳出循環(huán)

[root@tx3 ~]# awk 'BEGIN {FS=":"} {for(i=NF;i>=2;i--) {printf $i ";"};print $1}' p1

/bin/bash;/root;root;0;0;x;root

/sbin/nologin;/bin;bin;1;1;x;bin

/sbin/nologin;/sbin;daemon;2;2;x;daemon

/sbin/nologin;/var/adm;adm;4;3;x;adm

[root@tx3 ~]# cat num

2 8 9

8 4 6

3 5 7

[root@tx3 ~]# awk '{ max=0; i=1; while (i<=NF) { if (max<$i) {max=$i} i++} print max}' num

9

8

7

(5)awk數(shù)組

例 ? 使用變量作為數(shù)組下標(biāo)

另外一種讀取方式(這種是無序的,j是變量,a是數(shù)組)

數(shù)組有序

(6)函數(shù)

@1split 切割字符串

split("等待被切割的字符串",數(shù)組名,"切割用的分隔符")

[root@tx3 ~]# awk 'BEGIN{split("2012/08/23",da,"/");print da[2],da[3],da[1]}'

08 23 2012

@2toupper() 小寫轉(zhuǎn)大寫

tolower() 大寫轉(zhuǎn)小寫

[root@tx3 ~]# awk '{print toupper($0)}' p1 |head -3

ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH

BIN:X:1:1:BIN:/BIN:/SBIN/NOLOGIN

DAEMON:X:2:2:DAEMON:/SBIN:/SBIN/NOLOGIN

@3sub() ?局部替換

gsub() 全局替換

sub(/要替換的內(nèi)容/,"替換成什么內(nèi)容")

gsub(/要替換的內(nèi)容/,"替換成什么內(nèi)容")

gsub(/要替換的內(nèi)容/,"替換成什么內(nèi)容",指定字段如$7)

例:

[root@tx3 ~]# awk -F: '{sub(/root/,"r00t");print}' p1

r00t:x:0:0:root:/root:/bin/bash

例:

[root@tx3 ~]# awk -F: '{gsub(/root/,"r00t");print}' p1

r00t:x:0:0:r00t:/r00t:/bin/bash

operator:x:11:0:operator:/r00t:/sbin/nologin

例:

[root@tx3 ~]# awk -F[:/] '{gsub(/root/,"r00t",$7);print}' p1

root x 0 0 root ?r00t ?bin bash

operator x 11 0 operator ?r00t ?sbin nologin

@4.length() 計(jì)算字符串的長度

[root@tx3 ~]# awk -F: '{print length($1),$1}' p1

4 root

3 bin

6 daemon

3 adm

@5. 數(shù)學(xué)計(jì)算

[root@tx3 ~]# awk 'BEGIN{print sin(30)}'

-0.988032

[root@tx3 ~]# awk 'BEGIN{print cos(60)}'

-0.952413

[root@tx3 ~]# awk 'BEGIN{print int(22/6)}'

3

[root@tx3 ~]# awk 'BEGIN{print sqrt(3)}'

1.73205

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容