《Linux命令行与shell脚本编程大全》第二十二章 gawk进阶
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进阶的更多相关文章
- 《Linux命令行与shell脚本编程大全》 第六章环境变量
很多程序和脚本都通过环境变量来获取系统信息.存储临时数据和配置信息. 6.1 什么是环境变量: bash shell用一个叫环境变量(environment variable)的特性来存储有关shel ...
- 《Linux命令行与shell脚本编程大全》第十三章 更多的结构化命令
本章讨论bash shell的循环命令for.while和until 13.1 for命令 重复执行一系列命令在编程中很常见. bash shell提供了for命令,允许你创建一个遍历一系列值的循环. ...
- 《Linux命令行与shell脚本编程大全》第十一章 构建基本脚本
11.1使用多个命令 $date;who // 命令列表,加入分号就可以,这样会依次执行.参见5.2.1节 注意区分$(date;who),这个是进程列表,会生成一个子shell来执行 Shel ...
- 《Linux命令行与shell脚本编程大全》 第三章 学习笔记
第三章:基本的bash shell命令 bash程序使用命令行参数来修改所启动shell的类型 参数 描述 -c string 从string中读取命令并处理他们 -r 启动限制性shell,限制用户 ...
- 《Linux命令行与shell脚本编程大全》第十七章 创建函数
可以将shell脚本代码放进函数中封装起来,这样就能在脚本中的任何地方多次使用它了. 17.1 基本的脚本函数 函数:是一个脚本代码块,可以为其命名并在代码中任何位置重用. 17.1.1 创建函数 有 ...
- 《Linux命令行与shell脚本编程大全》 第五章理解shell
5.1 1. cat /etc/passwd 可以查看每个用户自己的默认的shell程序. 2.默认的交互shell会在用户登录某个虚拟控制台终端时启动. 不过还有另外一个默认的shell是/bin/ ...
- 《Linux命令行与shell脚本编程大全》 第七章理解Linux文件权限
Linux沿用了Unix文件权限的方法,允许用户和组根据每个文件和目录的安全性设置来访问文件. 用户权限通过创建用户时分配的用户ID(UID)来跟踪的.每个用户有唯一的ID,但是登录时用的不是UID, ...
- 《Linux命令行与shell脚本编程大全》 第四章
4.1 监测程序 1. ps 默认只显示运行在当前控制台下的属于当前用户的进程. 可以接很多选项,比如 -A表示所有进程 -e等. 2. ps -l 查看进程更多信息 UID:启动这些进程的用 ...
- Linux命令行与shell脚本编程大全.第3版(文字版) 超清文字-非扫描版 [免积分、免登录]
此处免费下载,无需账号,无需登录,无需积分.收集自互联网,侵权通知删除. 点击下载:Linux命令行与shell脚本编程大全.第3版 (大小:约22M)
- 《Linux命令行与shell脚本编程大全 第3版》创建实用的脚本---11
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
随机推荐
- 安利一波那个叫做 hutool 的通用工具类库
摘自3.1.1版本作者发布原话,当时看到有点说不上的情绪,为作者的坚持.热爱点个赞. 已经想不起来是怎样结识 Hutool 的,但 Hutool 伴随几个项目的推进,获得了同事一致好评. 没经过实践和 ...
- jQuery图片轮播(一)轮播实现并封装
利用面向对象自己动手写了一个封装好的jquery轮播对象,可满足一般需求,需要使用时只需调用此对象的轮播方法即可. demo:https://github.com/zsqosos/shopweb ...
- Spring事务的传播行为和隔离级别
事物注解方式: @Transactional [一]传播行为: 使用方法:@Transactional(propagation=Propagation.REQUIRED) Require:支持当前事务 ...
- oracle实用基础
Oracle修改字段名 alter table 表名 rename column 旧字段名 to 新字段名例子:alter table T_STUDENT rename column NAME to ...
- 理解typename的两个含义
理解typename的两个含义 问题:在下面的 template declarations(模板声明)中 class 和 typename 有什么不同? template<class T> ...
- 【Win 10 应用开发】UI Composition 札记(二):基本构件
在上一篇中,老周用一个示例,演示了框架视图的创建过程,在本篇中,老周将给大伙伴们说一下 Composition 构建 UI 的一些“零件”. UI Composition 有一个核心类——对,就是 C ...
- 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 ...
- dom4j解析xml文档全面介绍
一.dom4j介绍 dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点, ...
- YARN到底是怎么一回事?
文章思路: 首先提出第一代MRv1(MapReduce Version1.0)的局限性,然后解释YARN是怎么克服这些局限性的,接着说了YARN的编程模型,说了YARN的组成,YARN的通信协议和YA ...
- Python通过跳板机链接MySQL的一种方法