gawk是一门功能丰富的编程语言,你可以通过它所提供的各种特性来编写好几程序处理数据。

22.1 使用变量

gawk编程语言支持两种不同类型的变量:

内建变量和自定义变量

22.1.1 内建变量

gawk程序使用内建变量来引用程序数据里的一些特殊功能

1.字段和记录分隔符变量

数据字段变量:允许你使用美元符和字段在该记录中的位置值来引用记录对应的字段。

要引用第一个字段就用变量$1,第二个就用$2,….以此类推。

数据字段是由分隔符来划定的。默认字段分隔符是一个空白字符,也就是空格或者制表符。

有一组内建变量用于控制gawk如何处理输入输出数据中的字段和记录,见下表:

变量

描述

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

《Linux命令行与shell脚本编程大全》第二十二章 gawk进阶的更多相关文章

  1. 《Linux命令行与shell脚本编程大全》 第六章环境变量

    很多程序和脚本都通过环境变量来获取系统信息.存储临时数据和配置信息. 6.1 什么是环境变量: bash shell用一个叫环境变量(environment variable)的特性来存储有关shel ...

  2. 《Linux命令行与shell脚本编程大全》第十三章 更多的结构化命令

    本章讨论bash shell的循环命令for.while和until 13.1 for命令 重复执行一系列命令在编程中很常见. bash shell提供了for命令,允许你创建一个遍历一系列值的循环. ...

  3. 《Linux命令行与shell脚本编程大全》第十一章 构建基本脚本

    11.1使用多个命令 $date;who   //  命令列表,加入分号就可以,这样会依次执行.参见5.2.1节 注意区分$(date;who),这个是进程列表,会生成一个子shell来执行 Shel ...

  4. 《Linux命令行与shell脚本编程大全》 第三章 学习笔记

    第三章:基本的bash shell命令 bash程序使用命令行参数来修改所启动shell的类型 参数 描述 -c string 从string中读取命令并处理他们 -r 启动限制性shell,限制用户 ...

  5. 《Linux命令行与shell脚本编程大全》第十七章 创建函数

    可以将shell脚本代码放进函数中封装起来,这样就能在脚本中的任何地方多次使用它了. 17.1 基本的脚本函数 函数:是一个脚本代码块,可以为其命名并在代码中任何位置重用. 17.1.1 创建函数 有 ...

  6. 《Linux命令行与shell脚本编程大全》 第五章理解shell

    5.1 1. cat /etc/passwd 可以查看每个用户自己的默认的shell程序. 2.默认的交互shell会在用户登录某个虚拟控制台终端时启动. 不过还有另外一个默认的shell是/bin/ ...

  7. 《Linux命令行与shell脚本编程大全》 第七章理解Linux文件权限

    Linux沿用了Unix文件权限的方法,允许用户和组根据每个文件和目录的安全性设置来访问文件. 用户权限通过创建用户时分配的用户ID(UID)来跟踪的.每个用户有唯一的ID,但是登录时用的不是UID, ...

  8. 《Linux命令行与shell脚本编程大全》 第四章

    4.1 监测程序 1. ps  默认只显示运行在当前控制台下的属于当前用户的进程.  可以接很多选项,比如 -A表示所有进程  -e等. 2. ps -l  查看进程更多信息 UID:启动这些进程的用 ...

  9. Linux命令行与shell脚本编程大全.第3版(文字版) 超清文字-非扫描版 [免积分、免登录]

    此处免费下载,无需账号,无需登录,无需积分.收集自互联网,侵权通知删除. 点击下载:Linux命令行与shell脚本编程大全.第3版 (大小:约22M)

  10. 《Linux命令行与shell脚本编程大全 第3版》创建实用的脚本---11

    以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:

随机推荐

  1. 安利一波那个叫做 hutool 的通用工具类库

    摘自3.1.1版本作者发布原话,当时看到有点说不上的情绪,为作者的坚持.热爱点个赞. 已经想不起来是怎样结识 Hutool 的,但 Hutool 伴随几个项目的推进,获得了同事一致好评. 没经过实践和 ...

  2. jQuery图片轮播(一)轮播实现并封装

      利用面向对象自己动手写了一个封装好的jquery轮播对象,可满足一般需求,需要使用时只需调用此对象的轮播方法即可. demo:https://github.com/zsqosos/shopweb ...

  3. Spring事务的传播行为和隔离级别

    事物注解方式: @Transactional [一]传播行为: 使用方法:@Transactional(propagation=Propagation.REQUIRED) Require:支持当前事务 ...

  4. oracle实用基础

    Oracle修改字段名 alter table 表名 rename column 旧字段名 to 新字段名例子:alter table T_STUDENT rename column NAME to ...

  5. 理解typename的两个含义

    理解typename的两个含义 问题:在下面的 template declarations(模板声明)中 class 和 typename 有什么不同? template<class T> ...

  6. 【Win 10 应用开发】UI Composition 札记(二):基本构件

    在上一篇中,老周用一个示例,演示了框架视图的创建过程,在本篇中,老周将给大伙伴们说一下 Composition 构建 UI 的一些“零件”. UI Composition 有一个核心类——对,就是 C ...

  7. Codeforces Round #380 (Div. 2)D. Sea Battle

    D. Sea Battle time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  8. dom4j解析xml文档全面介绍

    一.dom4j介绍 dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点, ...

  9. YARN到底是怎么一回事?

    文章思路: 首先提出第一代MRv1(MapReduce Version1.0)的局限性,然后解释YARN是怎么克服这些局限性的,接着说了YARN的编程模型,说了YARN的组成,YARN的通信协议和YA ...

  10. Python通过跳板机链接MySQL的一种方法