Shell腳本之awk詳解

                       Shell腳本之awk詳解

一.基本介紹

1.awk:

  awk是一個強大的文本分析工具,在對文本文件的處理以及生成報表,awk是無可替代的。awk認爲文本文件都是結構化的,它將每一個輸入行定義爲一個記錄,行中的每個字符串定義爲一個域(段),域和域之間使用分割符分割。


2.功能:流控制、數學運算、進程控制、內置的變量和函數、循環和判斷


3.工作原理:

awk 會把每行進行一個拆分,用相應的命令對拆分出來的“段”進行處理。

(1)行工作模式,讀入文件的每一行,會把一行的內容,存到$0裏

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

(3)輸出的時候按照內置變量OFS(out FS),輸出

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

簡單實例

[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常用內置變量表:

1 $0             當前記錄(作爲單個變量)  

2 $1~$n          當前記錄的第n個字段,字段間由FS分隔  

3 FS             輸入字段分隔符 默認是空格  

4 NF             當前記錄中的字段個數,就是有多少列  

5 NR             已經讀出的記錄數,就是行號,從1開始  

6 RS             輸入的記錄他隔符默 認爲換行符  

7 OFS            輸出字段分隔符 默認也是空格  

8 ORS            輸出的記錄分隔符,默認爲換行符  

9 ARGC           命令行參數個數  

10 ARGV           命令行參數數組  

11 FILENAME       當前輸入文件的名字  

12 IGNORECASE     如果爲真,則進行忽略大小寫的匹配  

13 ARGIND         當前被處理文件的ARGV標誌符  

14 CONVFMT        數字轉換格式 %.6g  

15 ENVIRON        UNIX環境變量  

16 ERRNO          UNIX系統錯誤消息  

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

18 FNR            當前記錄數  

19 OFMT           數字的輸出格式 %.6g  

20 RSTART         被匹配函數匹配的字符串首  

21 RLENGTH        被匹配函數匹配的字符串長度  


二.print的簡單使用

例:打印整行: $0

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

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


例:打印每行的最後一個字段: $NF

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


例:打印第三個字段: $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


例:打印第一行最後一個字段

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

/bin/bash


例:打印最後一行最後一個字段

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


例:打印每行的倒數第二個字段,並在其後打印你好

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

/root nihao

/bin nihao

/sbin nihao


例:打印行號

[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


例:打印當前系統環境變量的某個特定值

[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個字段

[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 生成報表

%d        十進制有符號整數  

%u        十進制無符號整數  

%f        浮點數  

%s        字符串  

%c        顯示字符的ASCII碼  

%p        指針的值  

%e        科學技術法顯示數值  

%x        %X 無符號以十六進制表示的整數  

%o        無符號以八進制表示的整數  

%g        %G 以科學計數法或浮點數的格式顯示數值  

%%        顯示其自身  

修飾符:  

-:  左對齊    

+:  顯示數值符號  

N: 顯示


-F 指定段的分隔符

例:(1)生成報表



例:(2)小數問題

對小數取保留位的時候,四捨五入

對小數取整,不進行四捨五入

[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


四.awk的使用


(1)正則表達式

\(\)   \{\} 不支持

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


例[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)關係運算符

> < == != >= <=

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

例[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)邏輯運算符

&& || !

與 或 非

例[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)算數運算符

+ - * / %(取模(餘數)) ^(冪運算)


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

[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{ 動作;動作;... }  在處理文件之前,要執行的動作;只執行一次

END{ 動作;動作;... }    在處理完文件之後,要執行的動作;只執行一次

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

END:彙總的操作

getline可以從管道和標準輸入讀取輸入,然後傳遞給變量。


例:

[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


五.awk裏的流控制和循環

(1)簡單的條件判斷

語法:(表達式 ? 值1 : 值2) 如果表達式成立,輸出值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 (表達式

{

                動作1;動作2;...

}

}

   如果表達式成立,那麼執行動作。

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

tx great

tx1 great

tx2 good

(2)多支判斷


{

if (表達式)

{ 動作1;動作2;...}

else if (表達式)

{ 動作1;動作2;...}

else if (表達式)

{ 動作1;動作2;...}

......

else

{ 動作1;動作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


判斷的標準:

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)循環while


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

例:

[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循環


語法:

{

for(表達式)

{動作1;...}

}

表達式:分爲3部分:

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

(2)測試表達式   i<10

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

語句:

next 處理輸入行的下一個輸入行

exit 退出

continue 結束本次循環

break 跳出循環



[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數組


例   使用變量作爲數組下標

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


數組有序


(6)函數

@1split 切割字符串

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

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

08 23 2012


@2toupper() 小寫轉大寫

tolower() 大寫轉小寫

[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(/要替換的內容/,"替換成什麼內容")

gsub(/要替換的內容/,"替換成什麼內容")

gsub(/要替換的內容/,"替換成什麼內容",指定字段如$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() 計算字符串的長度

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

4 root

3 bin

6 daemon

3 adm


@5. 數學計算

[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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章