|
9.gawk应用实现
(1)内建变量;
数据字段变量:
允许你使用美元符号($)和数据字段在数据行中位置对应的数值来引用该数据行中的字段
字段分隔符:
默认情况下,字段分隔符是一个空白字符,也就是空格符或制表符(tab)。在命令行下使用命令行参数-F或者在gawk程序中使用特殊的内置变量FS来更改字段分隔符
变量汇总:
FIELDWIDTHS 由空格分隔开的定义了每个数据字段确切宽度的一列数字
FS 输入字段分隔符
RS 输入数据行分隔符
OFS 输出字段分隔符
ORS 输出数据行分隔符
变量FS和OFS定义了gawk如何处理数据流中的数据字段
[root@ahui ~]# cat data1
data11,data12,data13,data14,data15
data21,data22,data23,data24,data25
data31,data32,data33,data34,data35
[root@ahui ~]# awk 'BEGIN{FS=","; OFS="-"} {print $1,$2,$3}' data1
data11-data12-data13
data21-data22-data23
data31-data32-data33
FIELDWIDTHS变量允许你读取数据行,而不用字段分隔符来划分字段。一旦设置了FIELDWIDTHS变量,gawk就会忽略FS变量,而根据提供的字段宽度大小来计算字段
[root@ahui ~]# cat data1b
1005.3847887.37
133-2.374893.23
23987.8237488.9
[root@ahui ~]# awk 'BEGIN{FIELDWIDTHS="3 5 2 5"} {print $1,$2,$3,$4}' data1b
100 5.384 78 87.37
133 -2.37 48 93.23
239 87.82 37 488.9
默认情况下,gawk将RS和ORS设为换行符,但是有时会碰到数据流中字段占了多行的情况。
经典的例子就是包含地址和电话号码的数据,其中地址和电话号码各占一行
[root@ahui ~]# cat data2
Riley Mullen
123 main street
Chicago, IL 60601
(312)555-2378
Frank Williams
123 main street
Chicago, IL 60601
(312)234-3253
Haley Snell
123 main street
Chicago, IL 60601
(312)123-2374
[root@ahui ~]# gawk 'BEGIN{FS="\n"; RS=""} {print $1,$4}' data2
Riley Mullen (312)555-2378
Frank Williams (312)234-3253
Haley Snell (312)123-2374
只需把FS变量设置成换行符。这就表明数据流中的每行都是一个单独的字段,每行上的所有数据都属于同一个字段。
接着只需把RS变量设置成空字符串,然后在数据行间留一个空白行。gawk会把每个空白行当做一个数据行分隔符
2)数据变量:
ARGC 当前命令行参数个数
ARGIND 当前文件在ARGV中的位置
ARGV 包含命令行参数的数组
CONVFMT 数字的转换格式(参见printf语句);默认值为%.6 g
ENVIRON 当前shell环境变量及其值组成的关联数组
ERRNO 当读取或关闭输入文件发生错误时的系统错误号
FILENAME 用作gawk输入数据的数据文件的文件名
FNR 当前数据文件中的数据行数
IGNORECASE 设成非零值时,忽略gawk命令中出现的字符串的字符大小写
NF 数据文件中的字段总数
NR 已处理的输入数据行数目
OFMT 数字的输出格式;默认值为%.6 g
RLENGTH 由match函数所匹配的子字符串的长度
RSTART 由match函数所匹配的子字符串的起始位置
相关实例:
[root@ahui ~]# gawk 'BEGIN{print ARGC,ARGV[1]}' data1
2 data1
注意:ARGC变量表明命令行上有两个参数,这包括gawk命令和data1参数(记住,程序脚本并不算参数)。
ARGV数组从代表该命令的索引0开始,第一个数组值是gawk命令后的第一个命令行参数。
[root@ahui ~]# gawk '
> BEGIN{
> print ENVIRON["HOME"]
> print ENVIRON["PATH"]
> }'
/root
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
注意:ENVIRON变量使用关联数组来提取shell环境变量。关联数组用文本作为数组的索引值,而不用数值。可用这种方式来从shell中提取任何环境变量的值来在gawk程序中使用。
[root@ahui ~]# gawk 'BEGIN{FS=":"; OFS=":"} {print $1,$NF}' /etc/passwd
root:/bin/bash
bin:/sbin/nologin
daemon:/sbin/nologin
adm:/sbin/nologin
lp:/sbin/nologin
sync:/bin/sync
shutdown:/sbin/shutdown
halt:/sbin/halt
mail:/sbin/nologin
uucp:/sbin/nologin
operator:/sbin/nologin
games:/sbin/nologin
gopher:/sbin/nologin
ftp:/sbin/nologin
nobody:/sbin/nologin
dbus:/sbin/nologin
usbmuxd:/sbin/nologin
vcsa:/sbin/nologin
rpc:/sbin/nologin
rtkit:/sbin/nologin
avahi-autoipd:/sbin/nologin
abrt:/sbin/nologin
rpcuser:/sbin/nologin
nfsnobody:/sbin/nologin
haldaemon:/sbin/nologin
gdm:/sbin/nologin
ntp:/sbin/nologin
apache:/sbin/nologin
saslauth:/sbin/nologin
postfix:/sbin/nologin
pulse:/sbin/nologin
sshd:/sbin/nologin
tcpdump:/sbin/nologin
ahui:/bin/bash
注意:NF变量允许你指定数据行中的最后一个数据字段,即NF变量含有数据文件中最后一个数据字段的数字值。可以在它前面加个美元符将它用作字段变量。
[root@ahui ~]# gawk '
> BEGIN{FS=","}
> {print $1, "FNR="FNR, "NR="NR}
> END{print "There were",NR,"records processed"}' data1 data1
data11 FNR=1 NR=1
data21 FNR=2 NR=2
data31 FNR=3 NR=3
data11 FNR=1 NR=4
data21 FNR=2 NR=5
data31 FNR=3 NR=6
There were 6 records processed
注意:FNR变量的值在gawk处理第二个文件时被重置了,而NR变量则在进入第二个数据文件后继续计数
注意变量赋值的语法结构:"FNR="FNR。引号位置错了会出现语法错误
(2)自定义变量
[root@ahui ~]# gawk '
> BEGIN{
> testing="This is a test"
> print testing
> }'
This is a test
注意:gawk编程语言包含了用来处理数字值的标准数学操作符,其中包括求余符号(%)和幂运算符号(^或**)
2)在命令行上给变量赋值
[root@ahui ~]# cat script1
BEGIN{FS=","}
{print $n}
[root@ahui ~]# gawk -f script1 n=2 data1
data12
data22
data32
这个特性允许你改变脚本的行为而不需要修改实际的脚本代码。
使用命令行参数来定义变量值会有个问题。在你设置了变量后,这个值在代码的BEGIN部分不可用
[root@ahui ~]# cat script2
BEGIN{print "The starting value is",n; FS=","}
{print $n}
[root@ahui ~]# gawk -f script2 n=3 data1
The starting value is
data13
data23
data33
可以用-v命令行参数来解决这个问题。它允许你指定在BEGIN代码部分之前设定的变量。在命令行上,-v命令行参数必须放在脚本代码之前
[root@ahui ~]# gawk -v n=3 -f script2 data1
The starting value is 3
data13
data23
data33
(3)处理数组
gawk编程语言使用关联数组来提供数组功能,关联数组跟数字数组不同之处在于它的索引值可以是任意文本字符串。每个索引字符串都必须是唯一的,并唯一地标识赋给它的数据元素。
1)定义数组变量
数组变量赋值的格式如下;
var[index] = element
其中var是变量名,index是关联数组的索引值,element是数据元素值。
[root@ahui ~]# gawk 'BEGIN{
> capital["Illinois"] = "Springfiled"
> print capital["Illinois"]
> }'
Springfiled
2)遍历数组变量
可以用for语句的一种特殊形式:
for (var in array)
{
statements
}
这个for语句会在每次将关联数组array的下一个索引值赋给变量var时,执行一遍statements。重要的是记住这个变量是索引值而不是数据元素值。
[root@ahui ~]# gawk 'BEGIN{
> var["a"] = 1
> var["b"] = 2
> var["c"] = 3
> var["d"] = 4
> for (test in var)
> {
> print "Index:",test," - value:",var[test]
> }
> }'
Index: a - value: 1
Index: b - value: 2
Index: c - value: 3
Index: d - value: 4
3)删除数组变量
从关联数组中删除数组索引要用一个特别的命令:
delete array[index]
删除命令会从数组中删除关联索引值和相关的数据元素值
[root@ahui ~]# gawk 'BEGIN{
> var["a"] = 1
> var["g"] = 2
> for (test in var)
> {
> print "Index:",test," - value:",var[test]
> }
> delete var["g"]
> print "---"
> for (test in var)
> print "Index:",test," - Value:",var[test]
> }'
Index: a - value: 1
Index: g - value: 2
---
Index: a - Value: 1
(4)使用模式
1)正则表达式
在使用正则表达式时,正则表达式必须出现在它要控制的程序脚本的左花括号前:
[root@ahui ~]# gawk 'BEGIN{FS=","} /11/{print $1}' data1
data11
2)匹配操作符
匹配操作符(matching operate)允许将正则表达式限定在数据行中的特定数据字段。匹配操作符是波浪线(~)。
$1 ~ /^data/
$1变量代表数据行中的第一个数据字段,这个表达式会过滤出第一个字段以文本data开头的所有数据行。
[root@ahui ~]# gawk 'BEGIN{FS=","} $2 ~ /^data2/{print $0}' data1
data21,data22,data23,data24,data25
也可以使用!符号来排除正则表达式的匹配:
$1 !~ /expression/
[root@ahui ~]# gawk '$1 !~ /root/{print $1,$NF}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System bus:/:/sbin/nologin
usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
vcsa:x:69:69:virtual owner:/dev:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/cache/rpcbind:/sbin/nologin
rtkit:x:499:497:RealtimeKit:/proc:/sbin/nologin rtkit:x:499:497:RealtimeKit:/proc:/sbin/nologin
avahi-autoipd:x:170:170:Avahi Stack:/var/lib/avahi-autoipd:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin
rpcuser:x:29:29:RPC User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous User:/var/lib/nfs:/sbin/nologin
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin gdm:x:42:42::/var/lib/gdm:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin ntp:x:38:38::/etc/ntp:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin apache:x:48:48:Apache:/var/www:/sbin/nologin
saslauth:x:498:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin
pulse:x:497:496:PulseAudio Daemon:/var/run/pulse:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin tcpdump:x:72:72::/:/sbin/nologin
ahui:x:500:500:ahuihaerbin:/home/ahui:/bin/bash ahui:x:500:500:ahuihaerbin:/home/ahui:/bin/bash
3)数学表达式
可以使用任意的普通股数学比较表达式
x == y:值x等于y
x <= y:
x < y
x >= y
x > y
可以对文本数据使用表达式,但是它跟正则表达式不同,表达式必须完全匹配。
[root@ahui ~]# gawk -F, '$1 == "data"{print $1}' data1
[root@ahui ~]# gawk -F, '$1 == "data11"{print $1}' data1
data11
(5)结构化命令
[root@ahui ~]# cat data4
10
5
13
50
34
[root@ahui ~]# gawk '{
> if ($1 > 20)
> {
> x = $1 * 2
> print x
> }
> }' data4
100
68
gawk的if语句也支持else子句,允许在if语句条件不成立的情况下执行一条或多条语句
[root@ahui ~]# gawk '{
> if ($1 > 20)
> {
> x = $1 * 2
> print x
> } else
> {
> x = $1 / 2
> print x
> }}' data4
5
2.5
6.5
100
68
也可以在单行上使用else子句,但必须在if语句部分使用分号:
if (condition) statement1; else statement2
[root@ahui ~]# gawk '{if ($1 > 20) print $1 * 2; else print $1 / 2}' data4
5
2.5
6.5
100
68
2)while语句
while语句的格式:
while (condition)
{
statements
}
while循环允许遍历一组数据,并检查结束迭代的条件
[root@ahui ~]# gawk '{
total = 0
i = 1
while (i < 4)
{
total += $i
i++
}
avg = total / 3
print "Average:" ,avg
}' data5
Average: 128.333
Average: 137.667
Average: 176.667
[root@ahui ~]# gawk '{
> total = 0
> i = 1
> while (i < 4)
> {
> total += $i
> if (i == 2)
> break
> i++
> }
> avg = total / 2
> print "The average of the first two data elements is:",avg
> }' data5
The average of the first two data elements is: 125
The average of the first two data elements is: 136.5
The average of the first two data elements is: 157.5
3)do-while语句
do-while语句类似于while语句,但会在检查条件语句之前执行命令。格式为:
do
{
statement
} while (condition)
这种格式保证了语句会在条件被评估之前至少执行一次
4)for语句
gawk支持C风格的for循环:
for( variable assignment; condition; iteration process)
(6)格式化打印
因此要用到格式化打印,我们需要printf命令。格式:
printf "format string", var1, var2...
format string是格式化输出地关键。它会用到文本元素和格式化指定符来具体指定如何呈现格式化输出。
格式化指定符采用如下格式:
%[modifier]control-letter
其中control-letter是指明显示什么类型数据值的单字符码,而modifier定义了另一个可选的格式化特性。
c 将一个数作为ASCII字符显示
d 显示一个整数值
i 显示一个整数值(跟d一样)
e 用科学计数法显示一个数
f 显示一个浮点数
g 用科学计数法或浮点数中较短的显示
o 显示一个八进制值
s 显示一个文本字符串
x 显示一个十六进制值
X 显示一个十六进制值,但用大写字母A-F
除了控制字母外,还有3种修饰符可以用来进一步控制输出
width:
指定了输出字段最小宽度的数字值。如果输出短于这个值,printf会向右对齐,并用空格来填充这段空间。如果输出比指定的宽度还要长,它就会覆盖width值。
prec:
指定了浮点数中小数点后面位数的数字值,或者文本字符串中显示的最大字符数。
-(减号):
减号指明在向格式化空间中放入数据时采用左对齐而不是右对齐
[root@ahui ~]# gawk 'BEGIN{FS="\n"; RS=""} {printf "%s %s\n", $1, $4}' data2
Riley Mullen (312)555-2378
Frank Williams (312)234-3253
Haley Snell (312)123-2374
注意:我们需要自己手动在printf命令的末尾添加换行符来生成新行。没加的话,printf命令会继续用同一行来打印后续输出。
如果你需要用几个单独的printf命令来在同一行上打印多个输出,它会非常有用:
[root@ahui ~]# gawk 'BEGIN{FS=","} {printf "%s ", $1} END{printf "\n"}' data1
data11 data21 data31
接着我们用修饰符来格式化第一个字符串值:
[root@ahui ~]# gawk 'BEGIN{FS="\n"; RS=""} {printf "%16s %s\n",$1, $4}' data2
Riley Mullen (312)555-2378
Frank Williams (312)234-3253
Haley Snell (312)123-2374
通过添加一个值为16的修饰符,我们强制第一个字符串的输出采用16位字符。默认情况下,printf命令使用右对齐来将数据放到格式化空间中。要改成左对齐,只要给修饰符加一个减号就可以了。
[root@ahui ~]# gawk 'BEGIN{FS="\n"; RS=""} {printf "%-16s %s\n", $1, $4}' data2
Riley Mullen (312)555-2378
Frank Williams (312)234-3253
Haley Snell (312)123-2374
(7)自定义函数
函数名必须能够唯一标识函数
2)使用自定义函数
在定义函数时,它必须出现在所有代码块之前(包括BEGIN代码块)。
[root@ahui ~]# gawk '
> function myprint()
> {
> printf "%-16s - %s\n", $1, $4
> }
> BEGIN{FS="\n"; RS=""}
> {
> myprint()
> }' data2
Riley Mullen - (312)555-2378
Frank Williams - (312)234-3253
Haley Snell - (312)123-2374
3)创建函数库
首先创建一个存储所有gawk函数的文件
[root@ahui ~]# cat funclib
function myprint()
{
printf "%-16s - %s\n", $1, $4
}
function myrand()
{
return int(limit * rand())
}
function printthird()
{
printf $3
}
注意:不能将-f命令行参数和内联gawk脚本放到一起使用,不过可以在同一个命令行中使用多个-f参数
[root@ahui ~]# cat script4
BEGIN{ FS="\n"; RS="" }
{
myprint()
}
[root@ahui ~]# gawk -f funclib -f script4 data2
Riley Mullen - (312)555-2378
Frank Williams - (312)234-3253
Haley Snell - (312)123-2374
(责任编辑:最模板) |

ecshop仿聚美模板免费整站
人气:3737
Destoon B2B行业分类29328条阿
人气:3376
ecshop仿梦芭莎2013最新版免
人气:4041
ecshop仿好乐买模板|ecshop鞋
人气:712
大气asp科技安防电子公司
人气:738
Prestashop多用途英文服饰商
人气:154