《Linux命令行与shell脚本编程大全》第二十二章 gawk进阶

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

22.1 使用变量

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

内建变量和自定义变量

22.1.1 内建变量

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

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

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

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

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

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


变量


描述


FIELDWIDTHS


有空格分隔的一列数字,定义每个数据字段的确切宽度


FS


输入字段分隔符


RS


输入记录分隔符


OFS


输出字段分隔符


ORS


输出记录分隔符

1)print命令会自动将OFS变量的值放置在输出中的每个字段间。

实例:

[email protected]:~/shell/22zhang$ cat data1

data11,data12,data13,data14

data21,data22,data23,data24

data31,data32,data33,data34

data41,data42,data43,data44

data51,data52,data53,data54

[email protected]:~/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

[email protected]:~/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

[email protected]:~/shell/22zhang$

2) FIELDWIDTHS变量允许你不依靠字段分割符来读取记录。一旦这是了FILEDWIDTFS变量,gawk就会忽略FS变量。

警告:一旦设定了FIELDWIDTHS变量的值,就不能再改变了。这种方法并不适用于变长的字段

有写数据没有指定分隔符,而是放在特定的列,这时候就可以用FIELDWIDTHS了:

例子:

[email protected]:~/shell/22zhang$ cat data2

1005.3246782.37

115-2.343324.08

05828.3452433.1

[email protected]:~/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

[email protected]:~/shell/22zhang$

3)RS和ORS定义了gawk程序如何处理数据流中的字段。默认这两个都是换行符

默认的RS表明,输入数据流中的每行新文本就是一条新记录

例子:

[email protected]:~/shell/22zhang$ cat data3

kobe bryant

24 Los Lakers

Los, road34

99038

Paul Gaoso

15 los Lakers

Los, road 38

23123

[email protected]:~/shell/22zhang$ gawk ‘BEGIN{FS="\n";RS=""} {print $1, $4}‘ data3

kobe bryant 99038

Paul Gaoso 23123

[email protected]:~/shell/22zhang$ gawk ‘BEGIN{FS="\n";RS=""} {print $1, $2}‘ data3

kobe bryant 24 Los Lakers

Paul Gaoso 15 los Lakers

[email protected]:~/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:

[email protected]:~/shell/22zhang$ gawk ‘BEGIN{print ARGC,ARGV[1]}‘ data2

2 data2

[email protected]:~/shell/22zhang$ gawk ‘BEGIN{print ENVIRON["HOME"]}‘

/home/xcy

xcy[email protected]:~/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

[email protected]:~/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变量则含有已处理过的记录总数

[email protected]:~/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

[email protected]:~/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

[email protected]:~/shell/22zhang$

当处理第2个文件时,FNR又被置成1了,但是NR还是继续增加的。

注意:

1)在shell脚本中使用gawk时,应该将gawk的命令放到不同的行,便于理解和阅读

2)如果在不同的shell脚本中使用了相同的gawk脚本,应该把gawk放在一个单独的文件中。再用-f参数去引用它。

22.1.2自定义变量

变量名可以是字母下划线开头,还可以有数字。并且变量名区分大小写

1.在脚本中给变量赋值

可以对变量进行修改,可以进行数学运算

例子:

[email protected]:~/shell/22zhang$ gawk ‘

> BEGIN{

> test="hahaha, i am test"

> print test}‘

hahaha, i am test

[email protected]:~/shell/22zhang$ gawk ‘

BEGIN{

test="hahaha, i am test"

print test

> test=156

> print test

> }‘

hahaha, i am test

156

[email protected]:~/shell/22zhang$ gawk ‘

> BEGIN{

> x=4

> x=x*3+4

> print x

> }‘

16

[email protected]:~/shell/22zhang$

2. 在命令行上给变量赋值

也可以用gawk命令行来给程序中的变量赋值。这允许你在正常的代码之外赋值。

[email protected]:~/shell/22zhang$ cat script

BEGIN{FS=","}

{print $n}

[email protected]:~/shell/22zhang$ gawk -f script n=3 data1

data13

data23

data33

data43

data53

[email protected]:~/shell/22zhang$

上面可以给n进行赋值,改变脚本的行为。

这样可以在不改变脚本代码的情况下就能改变脚本的行为

上面这样存在的问题是设置的变量在代码的BEGIN部分不可用

解决方法,用-v参数。它允许你在BEGIN代码之前设定变量,要放在脚本代码之前。

[email protected]y-virtual-machine:~/shell/22zhang$ cat script2

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

{print $n}

[email protected]:~/shell/22zhang$ gawk -v n=4 -f script2 data1

The starting value is 4

data14

data24

data34

data44

data54

[email protected]:~/shell/22zhang$

22.2 处理数组

gawk编程语言使用关联数组提供数组功能

关联数组跟数字数组不同之处在于它的索引值可以是任意文本字符串。

不需要用连续的数字来标识数组元素。关联数组用各种字符串来引用值

每个索引字符串都必须能够唯一标识赋给它的数据元素

22.2.1 定义数组变量

用标准赋值语句来定义数组变量。格式如下:

var[index]=element

var是变量名,index是关联数组的索引值 element是数据元素值

例子:

这里要加双引号,数字不用加,字符串需要加

[email protected]:~/shell/22zhang$ gawk ‘                     

BEGIN{

nba["kobe"]="bryant"

nba["cp3"]="paul"

print nba["kobe"]

print nba["cp3"]

}‘

bryant

paul

# 还可以进行数学运算。

[email protected]:~/shell/22zhang$ gawk ‘

> BEGIN{

> arr[1]=99

> arr[2]=77

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

> print "total =",total

> }‘

total = 176

[email protected]:~/shell/22zhang$

22.2.2 遍历数组变量

关联数组的索引可以是任何东西

遍历数组可以用for语句的一种特殊形式:

for (var in array)

{

statements

}

这个for语句会在每次循环时都将关联数组array的下一个索引值赋值给变量var,然后执行一遍statements

[email protected]:~/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]

}

}

[email protected]:~/shell/22zhang$ gawk -f script3

Index: a  - Value: hahah

Index: b  - Value: 2

Index: c  - Value: yutong keche

Index: d  - Value: 4

[email protected]:~/shell/22zhang$

22.2.3删除数组变量

格式如下:

delete array[index]

删除以后就没办法再用它来提取元素值了。

比如:

[email protected]:~/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]

}

}

[email protected]:~/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

[email protected]:~/shell/22zhang$

22.3 使用模式

gawk支持多种类型的匹配模式来过滤数据记录。

BEGIN和END关键字用来读取数据流之前或之后执行命令的特殊模式

22.3.1 正则表达式

可以用基础正则表达式(BRE)或扩展正则表达式(ERE)来选择程序脚本作用在数据流中的哪些行上。

使用正则表达式时,正则表达式必须出现在它要控制的程序脚本的左花括号前。

[email protected]:~/shell/22zhang$ cat script5

BEGIN{FS=","}

/11/{print $1, $2}

[email protected]:~/shell/22zhang$ gawk -f script5 data1

data11 data12

[email protected]:~/shell/22zhang$

正则表达式/11/匹配了字段中含有字符串11的记录。

22.3.2 匹配操作符

匹配操作符允许将正则表达式限定在记录中的特定数据字段。匹配操作符是~。

可以指定匹配操作符,数据字段变量以及要匹配的正则表达式

$1 ~ /^data/

$1变量代表记录中的第一个数据字段。

上面的例子会过滤出以data开头的所有记录。

取反: $1 !~ /^data1/   匹配第一个字段不以data1开头的记录

例子2:

// 匹配第2个字段为data2开头的记录,并且打印第1和第3个字段。$2表示第2个字段

[email protected]:~/shell/22zhang$ cat data1

data11,data12,data13,data14

data21,data22,data23,data24

data31,data32,data33,data34

data41,data42,data43,data44

data51,data52,data53,data54

[email protected]cy-virtual-machine:~/shell/22zhang$ gawk ‘BEGIN{FS=","} $2 ~ /^data2/{print $1, $3}‘ data1   data21 data23

[email protected]:~/shell/22zhang$ gawk ‘BEGIN{FS=","} $2 !~ /^data2/{print $1, $3}‘ data1  // 这里还可以取反,匹配第二个字段不以data2开头的记录。加个感叹号

data11 data13

data31 data33

data41 data43

data51 data53

[email protected]:~/shell/22zhang$

例子3:

[email protected]:~/shell/22zhang$ gawk ‘BEGIN{FS=":"} $1 ~ /^xcy/{print $1,":" $NF}‘ /etc/passwd

xcy :/bin/bash

[email protected]:~/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语言的差不多

例子:

[email protected]:~/shell/22zhang$ cat data4

3

5

34

467

1

[email protected]:~/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 "

         }

}

[email protected]cy-virtual-machine:~/shell/22zhang$ gawk -f ifscript data4

step 2 $1 == 3

step 3

$1 > 29

34

$1 > 29

467

step 3

[email protected]:~/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语言一样

例子:

[email protected]:~/shell/22zhang$ cat data5

100 110 120

170 180 190

300 310 320

[email protected]:~/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

}

[email protected]:~/shell/22zhang$ gawk -f script6 data5

i= 2

Average: 70

i= 2

Average: 116.667

i= 2

Average: 203.333

[email protected]:~/shell/22zhang$

22.4.3 do-while语句

和while语句类似,但是会在检查条件语句之前执行命令。格式如下:

do

{

statement

} while(condition)

这种格式保证了语句在条件被求值之前至少执行一次

例子:

[email protected]:~/shell/22zhang$ cat script7

{

total=0

i=1

do

{

         total += $i

         i++

} while(total < 300)

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

}

[email protected]:~/shell/22zhang$ gawk -f script7 data5

total: 330 i= 4

total: 350 i= 3

total: 300 i= 2

[email protected]:~/shell/22zhang$

22.4.4 for语句

支持C风格的for循环:

例子:

[email protected]:~/shell/22zhang$ cat script8

{

total=0

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

{

         total += $i

}

avg=total/3

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

}

[email protected]:~/shell/22zhang$ gawk -f script8 data5

Total: 330 Average: 110

Total: 540 Average: 180

Total: 930 Average: 310

[email protected]:~/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的例子:

[email protected]:~/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]

}

}

[email protected]:~/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

[email protected]:~/shell/22zhang$

注意看对var数组的数据元素进行排序了。排序后的数组放在test数组里面了。

索引值被替换成了数字。索引最大的对应数据元素也是最大的。

下面是split的例子:

[email protected]:~/shell/22zhang$ cat data1

data11,data12,data13,data14

data21,data22,data23,data24

data31,data32,data33,data34

data41,data42,data43,data44

data51,data52,data53,data54

[email protected]:~/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]

}

[email protected]:~/shell/22zhang$ gawk -f script10 data1

将每一行用FS字符(,)分开,放到了test数组上。再打印数组的数据。

count表示字段总数

22.6.3 时间函数


函数


描述


mktime(datadpace)


将一个按YYYYMMDDHHMMSS[DST]格式指定的日期转成时间戳值


strftime(format [,timestamp])


将当前时间的时间戳或timestamp(若提供的话)转化格式化日期(采用shell函数data()的格式)


systime()


返回当前时间的时间戳

例子:

[email protected]:~/shell/22zhang$ cat script11

BEGIN{

date=systime()

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

print day

}

[email protected]:~/shell/22zhang$ gawk -f script11

星期六, 十一月 25, 2017

[email protected]:~/shell/22zhang$

注意:BEGIN后面的{要挨着BEGIN写,不能换行写。

否则报错

[email protected]:~/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代码块)。

实例:

[email protected]:~/shell/22zhang$ cat data3

kobe bryant

24 Los Lakers

Los, road34

99038

Paul Gaoso

15 los Lakers

Los, road 38

23123

[email protected]:~/shell/22zhang$ cat fun1

function myprint()

{

         print "This is myprint() +++"

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

}

BEGIN{

FS="\n"

RS=""

}

{

myprint()

}

[email protected]:~/shell/22zhang$ gawk -f fun1 data3

This is myprint() +++

kobe bryant      - 99038

This is myprint() +++

Paul Gaoso       - 23123

[email protected]:~/shell/22zhang$

先格式化记录中的第一个和第四个数据字段。再输出

定义了函数就可以在程序的代码中随便使用了

22.7.3 创建函数库

可以将多个函数放到一个库文件中,这样就能在所有的gawk程序中使用了。

步骤:

1)先创建一个存储所有gawk函数的文件

[email protected]:~/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)就可以在脚本中使用啦

[email protected]:~/shell/22zhang$ cat usefunlib

BEGIN{

FS="\n"

RS=""

}

{

myprint()

}

[email protected]:~/shell/22zhang$ gawk -f funlib -f usefunlib data3

kobe bryant      - 99038

Paul Gaoso       - 23123

[email protected]:~/shell/22zhang$

要引用文件需要使用-f参数。可以在同一命令行中使用多个-f参数。

22.8 实例

假设有一个数据文件,里面有两支队伍每队2个人,每人3次的比赛成绩。要求总成绩和平均成绩:

[email protected]:~/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

下面是脚本:

[email protected]:~/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相加,就是总成绩了。最后求平均值

这里是运行情况:

[email protected]:~/shell/22zhang$ ./bowling.sh

Total for team1 is 656 The avgarge is 109.333

Total for team2 is 545 The avgarge is 90.8333

时间: 2024-11-04 22:59:43

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

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

很多程序和脚本都通过环境变量来获取系统信息.存储临时数据和配置信息. 6.1 什么是环境变量: bash shell用一个叫环境变量(environment variable)的特性来存储有关shell会话和工作环境的信息. 这项特性允许在内存中存储数据,以便程序能轻松访问到它们. 在bash shell中,分两类: 全局变量:对于shell会话和所有生成的子shell都是可见的 局部变量:只对创建的它们的shell可见 6.1.1全局环境变量 查看全局变量,  $env    $printen

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

本章讨论bash shell的循环命令for.while和until 13.1 for命令 重复执行一系列命令在编程中很常见. bash shell提供了for命令,允许你创建一个遍历一系列值的循环.每次迭代都使用其中一个值来执行已定义好的一组命令.下面是基本格式 for var in list do command done 在list参数中需要提供迭代中要用到的一系列值.会依次迭代下去.每次迭代中,var会包含列表中要用到的一系列值. do 和 done直接输入的命令可以是一条或多条标准的b

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

第三章:基本的bash shell命令 bash程序使用命令行参数来修改所启动shell的类型 参数 描述 -c string 从string中读取命令并处理他们 -r 启动限制性shell,限制用户在默认目录下活动 -i 启动交互性shell,允许用户输入 -s 从标准输入读取命令 环境变量PS1.PS2 PS1:控制默认命令行提示符格式 PS2:控制后续命令行提示符格式   bash shell提示符字符串中使用的特殊字符 字符 描述 \a 报警字符 \d “日 月 年”格式显示的日期 \e

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

可以将shell脚本代码放进函数中封装起来,这样就能在脚本中的任何地方多次使用它了. 17.1 基本的脚本函数 函数:是一个脚本代码块,可以为其命名并在代码中任何位置重用. 17.1.1 创建函数 有两种格式:name 是函数名 1) function name {          commands } 2)这种就比较接近c语言风格了 name() {          commands } 17.1.2 使用函数 跟其他shell命令一样,在行中指定函数名就好了. 在函数定义前使用函数,会收

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

4.1 监测程序 1. ps  默认只显示运行在当前控制台下的属于当前用户的进程.  可以接很多选项,比如 -A表示所有进程  -e等. 2. ps -l  查看进程更多信息 UID:启动这些进程的用户 PID:进程的进程ID PPID:父进程的进程ID C:进程生命周期中的CPU利用率 TTY:进程启动时的终端设备 TIME:运行进程需要的累计CPU时间 CMD:启动的程序名称 PRI:进程的优先级(数字越大代表越低的优先级) ADDR:进程的内存地址 F:内核分配给进程的系统标记 S:进程的

《Linux命令行与shell脚本编程大全》学习笔记(转)

第一部分:Linux命令行<Linux命令行与shell脚本编程大全> 第一章:初识Linux shell<Linux命令行与shell脚本编程大全> 第二章:走进shell<Linux命令行与shell脚本编程大全> 第三章:基本的bash shell命令<Linux命令行与shell脚本编程大全> 第四章:更多的bash shell命令<Linux命令行与shell脚本编程大全> 第五章:使用Linux环境变量<Linux命令行与she

&lt;&lt;linux命令行与shell脚本编程大全&gt;&gt;学习笔记(1)

一章初识linux shell 一.什么是linux 1.linux系统可大致划分为四部分: l Linux内核 l GNU工具组件 l 图形化桌面环境 l 应用软件 在linux系统里,这四部分中的每一部分都扮演着一个特别的角色,但如果将他们分开,每一部分都没太大的作用. 1)探究linux内核 Linux系统的核心是内核,内核控制着计算机系统上的所有硬件和软件,必要时分配硬件,有时需要执行软件. 内核基本负责以下四项主要功能: l 系统内存管理 l 软件程序管理 l 硬件设备管理 l 文件系

【持续更新中】Linux命令行与Shell脚本编程大全(第3版)读书笔记12-20章

<Linux命令行与Shell脚本编程大全(第3版)>读书笔记 第十二章 使用结构化命令 根据条件使脚本跳过某些命令,这样的命令称为结构化命令(structured command).结构化命令允许改变程序执行的顺序. If-then语句: If command Then Commands Fi 如果if后的command执行退出码是0(也就是执行成功了),then后面的语句就会被执行. 也可以写成: If command; then Commands Fi 注意了,if后的command结果

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

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

《Linux命令行与Shell脚本编程大全第2版.布卢姆》pdf

下载地址:网盘下载 内容简介  · · · · · · 本书是一本关于Linux 命令行与shell 脚本编程的全面教程.全书分为四部分:第一部分介绍Linuxshell 命令行:第二部分介绍shell 脚本编程基础:第三部分深入探讨shell 脚本编程的高级内容:第四部分介绍如何在现实环境中使用shell 脚本.本书不仅涵盖了详尽的动手教程和现实世界中的实用信息,还提供了与所学内容相关的参考信息和背景资料. 本书内容全面,语言简练,示例丰富,适合于linux 系统管理员及Linux 爱好者阅读