《Linux命令行與shell腳本編程大全》第二十二章 gawk進階

gawk是一門功能豐富的編程語言,你能夠經過它所提供的各類特性來編寫好幾程序處理數據。 linux

22.1 使用變量

gawk編程語言支持兩種不一樣類型的變量:正則表達式

內建變量和自定義變量shell

 

22.1.1 內建變量

gawk程序使用內建變量來引用程序數據裏的一些特殊功能編程

 

1.字段和記錄分隔符變量數組

數據字段變量:容許你使用美圓符和字段在該記錄中的位置值來引用記錄對應的字段。bash

要引用第一個字段就用變量$1,第二個就用$2,….以此類推。編程語言

 

數據字段是由分隔符來劃定的。默認字段分隔符是一個空白字符,也就是空格或者製表符。函數

 

有一組內建變量用於控制gawk如何處理輸入輸出數據中的字段和記錄,見下表:spa

變量命令行

描述

FIELDWIDTHS

有空格分隔的一列數字,定義每一個數據字段的確切寬度

FS

輸入字段分隔符

RS

輸入記錄分隔符

OFS

輸出字段分隔符

ORS

輸出記錄分隔符

 

1)print命令會自動將OFS變量的值放置在輸出中的每一個字段間。

實例:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat data1

data11,data12,data13,data14

data21,data22,data23,data24

data31,data32,data33,data34

data41,data42,data43,data44

data51,data52,data53,data54

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{FS=","; OFS="-"} {print $1,$2,$3}' data1

data11-data12-data13

data21-data22-data23

data31-data32-data33

data41-data42-data43

data51-data52-data53

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{FS=","; OFS="<-->"} {print $1,$2,$3}' data1

data11<-->data12<-->data13

data21<-->data22<-->data23

data31<-->data32<-->data33

data41<-->data42<-->data43

data51<-->data52<-->data53

xcy@xcy-virtual-machine:~/shell/22zhang$

 

2) FIELDWIDTHS變量容許你不依靠字段分割符來讀取記錄。一旦這是了FILEDWIDTFS變量,gawk就會忽略FS變量。

警告:一旦設定了FIELDWIDTHS變量的值,就不能再改變了。這種方法並不適用於變長的字段

 

有寫數據沒有指定分隔符,而是放在特定的列,這時候就能夠用FIELDWIDTHS了:

例子:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat data2

1005.3246782.37

115-2.343324.08

05828.3452433.1

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{FIELDWIDTHS="3 5 2 5"} {print $1,$2,$3,$4}' data2

100 5.324 67 82.37

115 -2.34 33 24.08

058 28.34 52 433.1

xcy@xcy-virtual-machine:~/shell/22zhang$

 

3)RS和ORS定義了gawk程序如何處理數據流中的字段。默認這兩個都是換行符

默認的RS代表,輸入數據流中的每行新文本就是一條新記錄

例子:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat data3

kobe bryant

24 Los Lakers

Los, road34

99038

 

Paul Gaoso

15 los Lakers

Los, road 38

23123

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{FS="\n";RS=""} {print $1, $4}' data3

kobe bryant 99038

Paul Gaoso 23123

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{FS="\n";RS=""} {print $1, $2}' data3

kobe bryant 24 Los Lakers

Paul Gaoso 15 los Lakers

xcy@xcy-virtual-machine:~/shell/22zhang$

 

上面的例子中,4行纔是一條記錄,因此指定FS=」\n」

每行只是一個字段。

如何判斷一個新的數據行的開始:解決方法計算RS變量設爲空。而後在數據記錄之間留一個空白行。gawk會把每一個空白行當作一個記錄分隔符。

 

說明:

默認的字段分隔符是空格,記錄分割符是換行符

上面的例子把字段分割符改爲了換行符,記錄分隔符編程了空白行(RS=」」

 

2. 數據變量

還有一些其餘的內建變量:

變量

描述

ARGC

當前命令行參數個數

ARGIND

當前文件在ARGV的位置

ARGV

包含命令行參數的數組

CONVFMT

數字的轉換格式,模式是%.6 g

ENVIRON

當前shell環境變量及其值組成的關聯數組

ERRNO

當讀取或關閉文件發生錯誤時的系統錯誤號

FILENAME

用做輸入數據的數據文件的文件名

FNR

當前數據文件的數據行數

IGNORECASE

設成非零值,忽略gawk命令中出現的字符串的字符大小寫

NF

數據文件中的字段總數

NR

已處理的輸入記錄數

OFMT

數字的輸出格式,默認值%.6 g

RLENGTH

由match函數所匹配的字符串的長度

RSTART

由match函數所匹配的字符串的起始位置

 

實例1:

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{print ARGC,ARGV[1]}' data2

2 data2

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{print ENVIRON["HOME"]}'

/home/xcy

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{print ENVIRON["HOME"]; print ENVIRON["PATH"]}'

/home/xcy

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/sbin/:/usr/bin:/usr/sbin:/home/xcy/Bt_A7/Bt_A7/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin

xcy@xcy-virtual-machine:~/shell/22zhang$

 ENVIRON[「HOME」] 從系統中提取HOME環境變量的值。

 

例子2:

當要在gawk程序中跟蹤數據字段和記錄時,變量FNR,NF和NR就很是方便了。

NF變量能夠在你不知道具體位置的狀況下指定記錄中的最後一個數據字段:

$gawk ‘BEGIN{FS=」:」; OFS=」:」} {print $1, $NF}’ /etc/passwd

假設NF爲7,那麼至關因而$7。打印最後一個字段

 

例子3:

FNR變量含有當前數據文件中已處理過的記錄數

NR變量則含有已處理過的記錄總數

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{FS=","} {print $1,"FNR="FNR}' data1

data11 FNR=1

data21 FNR=2

data31 FNR=3

data41 FNR=4

data51 FNR=5

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{FS=","} {print $1,"FNR="FNR, "NR="NR} END{print "There were ",NR," recordes"}' data1 data1

data11 FNR=1 NR=1

data21 FNR=2 NR=2

data31 FNR=3 NR=3

data41 FNR=4 NR=4

data51 FNR=5 NR=5

data11 FNR=1 NR=6

data21 FNR=2 NR=7

data31 FNR=3 NR=8

data41 FNR=4 NR=9

data51 FNR=5 NR=10

There were  10  recordes

xcy@xcy-virtual-machine:~/shell/22zhang$

 

當處理第2個文件時,FNR又被置成1了,可是NR仍是繼續增長的。

 

注意:

1)在shell腳本中使用gawk時,應該將gawk的命令放到不一樣的行,便於理解和閱讀

2)若是在不一樣的shell腳本中使用了相同的gawk腳本,應該把gawk放在一個單獨的文件中。再用-f參數去引用它。

 

 

22.1.2自定義變量

變量名能夠是字母下劃線開頭,還能夠有數字。而且變量名區分大小寫

1.在腳本中給變量賦值

能夠對變量進行修改,能夠進行數學運算

例子:

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk '

> BEGIN{

> test="hahaha, i am test"

> print test}'

hahaha, i am test

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk '

BEGIN{

test="hahaha, i am test"

print test

> test=156

> print test

> }'

hahaha, i am test

156

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk '

> BEGIN{

> x=4

> x=x*3+4

> print x

> }'

16

xcy@xcy-virtual-machine:~/shell/22zhang$

 

2. 在命令行上給變量賦值

也能夠用gawk命令行來給程序中的變量賦值。這容許你在正常的代碼以外賦值。

xcy@xcy-virtual-machine:~/shell/22zhang$ cat script

BEGIN{FS=","}

{print $n}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f script n=3 data1

data13

data23

data33

data43

data53

xcy@xcy-virtual-machine:~/shell/22zhang$

上面能夠給n進行賦值,改變腳本的行爲。

這樣能夠在不改變腳本代碼的狀況下就能改變腳本的行爲

上面這樣存在的問題是設置的變量在代碼的BEGIN部分不可用

 

解決方法,用-v參數。它容許你在BEGIN代碼以前設定變量,要放在腳本代碼以前。

xcy@xcy-virtual-machine:~/shell/22zhang$ cat script2

BEGIN{print "The starting value is",n; FS=","}

{print $n}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -v n=4 -f script2 data1

The starting value is 4

data14

data24

data34

data44

data54

xcy@xcy-virtual-machine:~/shell/22zhang$

 

22.2 處理數組

gawk編程語言使用關聯數組提供數組功能

關聯數組跟數字數組不一樣之處在於它的索引值能夠是任意文本字符串。

不須要用連續的數字來標識數組元素。關聯數組用各類字符串來引用值

每一個索引字符串都必須可以惟一標識賦給它的數據元素

 

22.2.1 定義數組變量

用標準賦值語句來定義數組變量。格式以下:

var[index]=element

var是變量名,index是關聯數組的索引值 element是數據元素值

例子:

這裏要加雙引號,數字不用加,字符串須要加

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk '                     

BEGIN{

nba["kobe"]="bryant"

nba["cp3"]="paul"

print nba["kobe"]

print nba["cp3"]

}'

bryant

paul

# 還能夠進行數學運算。

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk '

> BEGIN{

> arr[1]=99

> arr[2]=77

> total=arr[1] + arr[2]

> print "total =",total

> }'

total = 176

xcy@xcy-virtual-machine:~/shell/22zhang$

 

 

22.2.2 遍歷數組變量

關聯數組的索引能夠是任何東西

遍歷數組能夠用for語句的一種特殊形式:

for (var in array)

{

  statements

}

這個for語句會在每次循環時都將關聯數組array的下一個索引值賦值給變量var,而後執行一遍statements

xcy@xcy-virtual-machine:~/shell/22zhang$ cat script3

BEGIN{

var["a"]="hahah"

var["b"]=2

var["c"]="yutong keche"

var["d"]=4

 

 

for (test in var)

{

         print "Index:",test," - Value:",var[test]

}

}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f script3

Index: a  - Value: hahah

Index: b  - Value: 2

Index: c  - Value: yutong keche

Index: d  - Value: 4

xcy@xcy-virtual-machine:~/shell/22zhang$

 

22.2.3刪除數組變量

格式以下:

delete array[index]

刪除之後就沒辦法再用它來提取元素值了。

好比:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat script4

BEGIN{

var["a"]="hahah"

var["b"]=2

var["c"]="yutong keche"

for (test in var)

{

         print "old: Index:",test," - Value:",var[test]

}

print "Now,delete array:"

delete var["c"]

 

for (test in var)

{

         print "new: Index:",test," - Value:",var[test]

}

}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f script4

old: Index: a  - Value: hahah

old: Index: b  - Value: 2

old: Index: c  - Value: yutong keche

Now,delete array:

new: Index: a  - Value: hahah

new: Index: b  - Value: 2

xcy@xcy-virtual-machine:~/shell/22zhang$

 

22.3 使用模式

gawk支持多種類型的匹配模式來過濾數據記錄。

BEGIN和END關鍵字用來讀取數據流以前或以後執行命令的特殊模式

 

22.3.1 正則表達式

能夠用基礎正則表達式(BRE)或擴展正則表達式(ERE)來選擇程序腳本做用在數據流中的哪些行上。

 

使用正則表達式時,正則表達式必須出如今它要控制的程序腳本的左花括號前。

xcy@xcy-virtual-machine:~/shell/22zhang$ cat script5

BEGIN{FS=","}

/11/{print $1, $2}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f script5 data1

data11 data12

xcy@xcy-virtual-machine:~/shell/22zhang$

正則表達式/11/匹配了字段中含有字符串11的記錄。

 

 

22.3.2 匹配操做符

匹配操做符容許將正則表達式限定在記錄中的特定數據字段。匹配操做符是~。

能夠指定匹配操做符,數據字段變量以及要匹配的正則表達式

$1 ~ /^data/

$1變量表明記錄中的第一個數據字段。

上面的例子會過濾出以data開頭的全部記錄。

取反: $1 !~ /^data1/   匹配第一個字段不以data1開頭的記錄

例子2:

// 匹配第2個字段爲data2開頭的記錄,而且打印第1和第3個字段。$2表示第2個字段

xcy@xcy-virtual-machine:~/shell/22zhang$ cat data1

data11,data12,data13,data14

data21,data22,data23,data24

data31,data32,data33,data34

data41,data42,data43,data44

data51,data52,data53,data54

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{FS=","} $2 ~ /^data2/{print $1, $3}' data1   data21 data23

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{FS=","} $2 !~ /^data2/{print $1, $3}' data1  // 這裏還能夠取反,匹配第二個字段不以data2開頭的記錄。加個感嘆號

data11 data13

data31 data33

data41 data43

data51 data53

xcy@xcy-virtual-machine:~/shell/22zhang$

 

例子3:

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk 'BEGIN{FS=":"} $1 ~ /^xcy/{print $1,":" $NF}' /etc/passwd

xcy :/bin/bash

xcy@xcy-virtual-machine:~/shell/22zhang$

 

例子4:! 用來排除正則表達式中的匹配

$ gawk -F: '$1 !~ /^xcy|^root/{print $1, ":" $NF}' /etc/passwd

-F 用來指定主句字段的分隔符

上面代表過濾第一個字段不以xcy開頭,或不以root開頭。

 

22.3.3 數學表達式

還能夠在匹配模式中用數學表達式。

例子:想顯示全部屬於root用戶組(組ID爲0)的系統用戶

$gawk –F: ‘$4 == 0{print $1}’ /etc/passwd

還能夠用任何常見的數學比較表達式: ==  <=  >=  >  <

 

匹配字符串:注意這時候是徹底匹配

$gawk –F, ‘$1==」data」 {print $1}’ data1

第一個字段必須是data,而不是包含data

 

22.4 結構化命令

 

22.4.1 if語句

給if語句定義一個求值的條件,並將其用圓括號括起來。

條件爲真在if後面的語句就會執行。

還能夠接上else。和C語言的差很少

例子:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat data4

3

5

34

467

1

xcy@xcy-virtual-machine:~/shell/22zhang$ cat ifscript

{

         if ($1 > 29)

         {

                   print "$1 > 29"  # 多條命令須要用{}括起來

                   print $1

         }

         else if($1 == 3) 

         {

                   print "step 2 $1 == 3"

         }       

         else

         {

                   print "step 3 "

         }

}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f ifscript data4

step 2 $1 == 3

step 3

$1 > 29

34

$1 > 29

467

step 3

xcy@xcy-virtual-machine:~/shell/22zhang$

 

還能夠在單行上使用else子句,這樣就須要在if後面接上分號;

$ gawk '{if($1 == 3) print $1" == 3 "; else print $1,"!= 3"}' data4

 

22.4.2 while 語句

基本格式:

while (condition)

{

  statement

}

 

while裏面還能夠放break和continue。用起來跟C語言同樣

 

例子:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat data5

100 110 120

170 180 190

300 310 320

xcy@xcy-virtual-machine:~/shell/22zhang$ cat script6

{

total=0

i=1

while(i < 4)

{

         total += $i

         i++

         if(i==3)

         {

                   break

                   #continue

         }

         print "i=", i

}

avg=total/3

print "Average:",avg

}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f script6 data5

i= 2

Average: 70

i= 2

Average: 116.667

i= 2

Average: 203.333

xcy@xcy-virtual-machine:~/shell/22zhang$

 

 

 

22.4.3 do-while語句

和while語句相似,可是會在檢查條件語句以前執行命令。格式以下:

do

{

  statement

} while(condition)

 

這種格式保證了語句在條件被求值以前至少執行一次

例子:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat script7

{

total=0

i=1

do

{

         total += $i

         i++

} while(total < 300)

print "total:",total,"i=",i

}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f script7 data5

total: 330 i= 4

total: 350 i= 3

total: 300 i= 2

xcy@xcy-virtual-machine:~/shell/22zhang$

 

22.4.4 for語句

支持C風格的for循環:

例子:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat script8

{

total=0

for(i=1; i<4; i++)

{

         total += $i

}

avg=total/3

print "Total:",total,"Average:",avg

}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f script8 data5

Total: 330 Average: 110

Total: 540 Average: 180

Total: 930 Average: 310

xcy@xcy-virtual-machine:~/shell/22zhang$

 

 

22.5 格式化打印

print打印在如何顯示數據上並未提供多少控制。

下面介紹一個格式化打印命令,printf,和C語言的那個有點相似:

printf 「format string」 ,var1,var2…

前面也是格式化命令。跟C語言很像:

1)

%c 輸出字符, %d 整數值, %i 整數值,%e 用科學計數法顯示數

%f 浮點數,%g 科學計數法或浮點數顯示(較短的)

%o 八進制,%s 字符串

%x 十六進制小寫,%X 十六進制大寫

2)

還有三種修飾符能夠用來進一步控制輸出

width:指定輸出字段最小寬度的數字值。實際比這短,則會補充空格,不然按正常輸出

prec:指定浮點數中小數點後面的位數。或者文本字符串中顯示的最大字符數

-(減號):指明在格式化空間中放入數據時採用左對齊,而不是右對齊

例子:

$ cat data3

kobe bryant

24 Los Lakers

Los, road34

99038

 

Paul Gaoso

15 los Lakers

Los, road 38

23123

$ gawk 'BEGIN{FS="\n"; RS=""} {printf "%s %s\n", $1,$2}' data3  #正常輸出

kobe bryant 24 Los Lakers

Paul Gaoso 15 los Lakers

$ gawk 'BEGIN{FS="\n"; RS=""} {printf "%16s %s\n", $1,$2}' data3  #指定輸出字段最小寬度

     kobe bryant 24 Los Lakers

      Paul Gaoso 15 los Lakers

$ gawk 'BEGIN{FS="\n"; RS=""} {printf "%-16s %s\n", $1,$2}' data3  #指定左對齊

kobe bryant      24 Los Lakers

Paul Gaoso       15 los Lakers

還能夠指定浮點數格式

… {printf 「%5.1f\n」, avg} …

佔5位,小數點後只顯示一位。

 

22.6 內建函數

gawk提供了很多內建的函數,能夠進行常見的數學 字符串以及時間函數運算

 

22.6.1 數學函數

函數

描述

atan2(x,y)

x/y的反正切,x y以弧度爲單位

cos(x)

X的餘弦 x以弧度爲單位

exp(x)

X的指數函數

int(x)

X的整數部分,取靠近零一側的值

log(x)

X的天然對數

rand(x)

比0大比1小的隨機浮點數

sin(x)

正弦,x以弧度爲單位

sqrt(x)

X的平方根

srand(x)

爲計算隨機數指定一個種子值

and(v1,v2)

執行v1和v2的按位與運算

compl(val)

執行val的補運算

lshift(val,count)

Val的值左移count位

or(v1,v2)

V1和v2的按位或運算

rshift(val,count)

Val右移count位

xor(v1,v2)

V1和v2的異或運算

 

例子:

$ gawk 'BEGIN{x=rand(); print "x =",x}'

$gawk 'BEGIN{x=int(-7.6); print "x =",x}'

$ gawk 'BEGIN{x=sin(1.57); print "x =",x}'

$ gawk 'BEGIN{x=int(10*rand()); print "x =",x}'

$ gawk 'BEGIN{x=and(1,2); print "x =",x}'

$ gawk 'BEGIN{x=lshift(1,2); print "x =",x}'

$ gawk 'BEGIN{x=xor(1,2); print "x =",x}'

 

22.6.2 字符串函數

 

函數

描述

asort(s [,d])

將數組s按數據元素值排序。索引值會被替換成表示新的排序順序的連續數字。另外若是指定了d,則排序後的數組會存儲在數組d中。

asorti(s [,d])

將數組s按索引值排序。生成的數組會將索引值做爲數據元素值,用連續數字因此來代表排序順序。若指定了d,排序後是數組會存在d中

gensub(r,s,h [,t])

查找變量$0或目標字符串t(若提供的話)來匹配正則表達式r。

若是h是一個以g或G開頭的字符串,就用s替換掉匹配的文本。

若是h是數字,它表示要替換掉的第h處r匹配的地方

gsub(r,s [,t])

查找變量$0或目標字符串t(若提供的話)來匹配正則表達式。

若是找到了就所有替換成字符串s

index(s,t)

返回字符串t在字符串s中的索引值。若是沒找到返回0

length([s])

返回字符串s的長度,若是沒有指定的話返回$0的長度

match(s, r [,a])

返回字符串s中正則表達式r出現位置的索引。若指定數組a,則會存儲s中匹配正則表達式的那部分

split(s, a [,r])

將s用FS字符或正則表達式r(若指定的話)分開放到數組a中。返回字段總數

sprintf(format,variables)

用提供的format和variables返回一個相似於printf輸出的字符串

sub(r,s [,t])

在變量$0或目標字符串t中查找正則表達式t的匹配。若找到了,就用字符串s替換掉第一處匹配

substr[s,i [,n]]

返回s從索引值i開始的n個字符組成的字符串。若未提供n,則返回s剩下的部分

tolower(s)

所有轉小寫

toupper(s)

所有轉大寫

 

 

有些用起來比較簡單,好比大小寫,求長度

$ gawk 'BEGIN{x=length("chong"); print "x =",x}'

$ gawk 'BEGIN{x=toupper("chong"); print "x =",x}'

 

下面是asort的例子:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat script9

BEGIN{

var["a"]=177

var["b"]=9

var["c"]=3

var["d"]=4444

var["e"]=566

asort(var,test)

for (i in test)

{

         print "Index:",i,"-value:",test[i]

}

}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f script9

Index: 4 -value: 566

Index: 5 -value: 4444

Index: 1 -value: 3

Index: 2 -value: 9

Index: 3 -value: 177

xcy@xcy-virtual-machine:~/shell/22zhang$

注意看對var數組的數據元素進行排序了。排序後的數組放在test數組裏面了。

索引值被替換成了數字。索引最大的對應數據元素也是最大的。

 

下面是split的例子:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat data1

data11,data12,data13,data14

data21,data22,data23,data24

data31,data32,data33,data34

data41,data42,data43,data44

data51,data52,data53,data54

xcy@xcy-virtual-machine:~/shell/22zhang$ cat script10

BEGIN{

FS=","

}

{

count=split($0,test)

for (i in test)

{

         print "Index:", i, "-Value:",test[i]

}

print "count =",count

#print test[1], test[5]

}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f script10 data1

 

將每一行用FS字符(,)分開,放到了test數組上。再打印數組的數據。

count表示字段總數

22.6.3 時間函數

函數

描述

mktime(datadpace)

將一個按YYYYMMDDHHMMSS[DST]格式指定的日期轉成時間戳值

strftime(format [,timestamp])

將當前時間的時間戳或timestamp(若提供的話)轉化格式化日期(採用shell函數data()的格式)

systime()

返回當前時間的時間戳

 

例子:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat script11

BEGIN{

date=systime()

day=strftime("%A, %B %d, %Y",date)

print day

}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f script11

星期六, 十一月 25, 2017

xcy@xcy-virtual-machine:~/shell/22zhang$

 注意:BEGIN後面的{要挨着BEGIN寫,不能換行寫。

不然報錯

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f script11

gawk: script11:2: BEGIN 塊必須有一個行爲部分

22.7 自定義函數

22.7.1 定義函數

必需要用function關鍵字,格式以下:

function name([variables])

{

  statement

}

函數名必須可以統一標識函數。能夠在調用的gawk程序中傳給這個函數一個或多個變量

 

例子:

// 打印記錄中的第三個字段

function printthird()

{

  print $3

}

 

還能夠用return返回值。

例子:

function myrand(limit)

{

  return int(limit * rand())

}

用法:

x=myrand(100)

 

22.7.2 使用自定義函數

定義函數時,它必須出如今全部代碼塊以前(包括BEGIN代碼塊)。

實例:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat data3

kobe bryant

24 Los Lakers

Los, road34

99038

 

Paul Gaoso

15 los Lakers

Los, road 38

23123

xcy@xcy-virtual-machine:~/shell/22zhang$ cat fun1

function myprint()

{

         print "This is myprint() +++"

         printf "%-16s - %s\n", $1,$4

}

BEGIN{

FS="\n"

RS=""

}

{

myprint()

}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f fun1 data3

This is myprint() +++

kobe bryant      - 99038

This is myprint() +++

Paul Gaoso       - 23123

xcy@xcy-virtual-machine:~/shell/22zhang$

 

先格式化記錄中的第一個和第四個數據字段。再輸出

定義了函數就能夠在程序的代碼中隨便使用了

 

22.7.3 建立函數庫

能夠將多個函數放到一個庫文件中,這樣就能在全部的gawk程序中使用了。

步驟:

1)先建立一個存儲全部gawk函數的文件

xcy@xcy-virtual-machine:~/shell/22zhang$ cat funlib

function mylib()

{

         print "mylib() +++"

}

function myprint()

{

         printf "%-16s - %s\n",$1,$4

}

function myrand(limit)

{

         return int(limit * rand())

}

function printthird()

{

         print $3

}

2)就能夠在腳本中使用啦

xcy@xcy-virtual-machine:~/shell/22zhang$ cat usefunlib

BEGIN{

FS="\n"

RS=""

}

{

myprint()

}

xcy@xcy-virtual-machine:~/shell/22zhang$ gawk -f funlib -f usefunlib data3

kobe bryant      - 99038

Paul Gaoso       - 23123

xcy@xcy-virtual-machine:~/shell/22zhang$

要引用文件須要使用-f參數。能夠在同一命令行中使用多個-f參數。

 

22.8 實例

假設有一個數據文件,裏面有兩支隊伍每隊2我的,每人3次的比賽成績。要求總成績和平均成績:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat scores.txt

Rich Blum,team1,100,115,99

Bar Blum,team1,110,118,114

Chr Bre,team2,120,80,90

Tim Bre,team2,125,70,60

 

下面是腳本:

xcy@xcy-virtual-machine:~/shell/22zhang$ cat bowling.sh

#!/bin/bash

for team in $(gawk -F, '{print $2}' scores.txt | uniq)

do

#       echo "team: $team"

         gawk -v team=$team 'BEGIN{FS=",";total=0}

         {

#                print "step1+++"

                   if ($2==team)

                   {

                            total += $3 + $4 + $5;

                   }

         }

         END{

                   avg = total / 6;

                   print "Total for",team,"is",total,"The avgarge is",avg

         }' scores.txt

done

腳本分析:

1)注意uniq這個關鍵字,這裏能夠排除同樣的。for語句是用來篩選隊名的。

2)for循環裏面,假如隊名是team1,那麼就先處理team1。會讀取全部記錄,將隊名都爲team1的記錄的$3 $4 $5相加,就是總成績了。最後求平均值

 

這裏是運行狀況:

xcy@xcy-virtual-machine:~/shell/22zhang$ ./bowling.sh

Total for team1 is 656 The avgarge is 109.333

Total for team2 is 545 The avgarge is 90.8333

相關文章
相關標籤/搜索