【Linux】gawk编辑器二
一、变量
gawk编程语言支持两种变量:内建变量和自定义变量。
1、内建变量
gawk使用内建变量来引用一些特殊的功能。
字段和记录分隔符变量
数据字段变量
此变量允许使用美元符号($)和字段在记录中的位置值来引用对应的字段。要引用记录中的第一个数据字段,就用变量 $1,要引用第二个数据字段,就用变量 $2,以此类推。
数据字段由字段分隔符划定。默认情况下,字段分隔符是一个空白字符:空格或制表符。可以通过使用命令行选项 -F ,或者使用特殊的内建变量 FS 修改字段分隔符。
FIELDWIDTHS | 由空格分隔的一列数字,定义了每个数据字段的确切宽度 |
FS | 输入字段分隔符 |
RS | 输入记录分隔符 |
OFS | 输出字段分隔符 |
ORS | 输出记录分隔符 |
默认情况下,gawk会将OFS变量的值设置为一个空格。print命令会自动将OFS变量的值置于输出的每个字段之间。
gawk 'BEGIN{FS=","} {print $1,$2,$3}' test2.txt
可以通过设置0FS变量,可以在输出中用任意字符串来分隔字段。
gawk 'BEGIN{FS=","; OFS="*"} {print $1,$2,$3}' test2.txt
FIELDWIDTHS变量可以不通过字段分隔符读取记录。一旦设置了此变量,gawk就会忽略FS变量,并根据提供的字段宽度计算字段。
gawk 'BEGIN{FIELDWIDTHS="2 4 5 3"} {print $1,$2,$3,$4}' test3.txt
变量RS和ORS定义了gawk对数据流中记录的处理方式。默认情况下,gawk会将RS和ORS设置为换行符。
默认的RS值表明,输入数据流中的每行文本就是一条记录。
包含地址和电话号码的数据中,占据了多行
可以把FS变量设置成换行符,这样就表明数据流中的每一行都是一个单独的字段,行内的所有数据都属于同一个数据字段。同时把RS变量设置成空字符串,然后在数据记录之间留一个空行。gawk就会把每一个空行视为记录分隔符。
gawk 'BEGIN{FS="\n"; RS=""} {print $1,$3}' test3.txt
gawk将文件中的每一行都视为一个字段,同时将空行作为记录分隔符。
数据变量
ENVIRON变量使用关联数组来提取shell环境变量,其中关联数组用文本而非数值作为数组索引。
如下所示,可以用这种方法从shell中提取任何环境变量的值,以供gawk脚本使用。
gawk '
BEGIN{
print ENVIRON["HOME"]
print ENVIRON["PATH"]
}'
变量FNR、NF和NR用于在gawk脚本中跟踪数据字段和记录。
变量NF可以让用户在不知道具体位置的情况下引用记录中的最后一个数据字段。NF变量含有数据文件中的最后一个字段的编号,在其前面加上美元符号,就把它用作字段变量。
gawk 'BEGIN{FS=":" ; OFS=":"} {print $1,$NF}' /etc/passwd
gawk 'BEGIN{FS=":" ; OFS=":"} {$NF}' /etc/passwd
注意看执行两条命令后打印出来的区别之处。
FNR变量包含当前数据文件中已处理过的记录数,NR变量包含已处理过的记录总数。
gawk 'BEGIN{FS=","}{print $1, "FNR="FNR}' test2.txt test2.txt
上述gawk脚本在命令行中指定了两个输入文件(都是test2.txt),此脚本会打印第一个字段和FNR变量的当前值。
gawk 'BEGIN{FS=","}{print $1, "FNR="FNR, "NR="NR}
END{print "这儿总共有",NR,"条记录被处理了"}'' test2.txt test2.txt
在gawk处理第二个数据文件时,FNR变量的值被重置了,而NR变量则继续计数。
因此,如果只使用一个数据文件作为输入,那么FNR和NR的值是相同的;如果使用多个数据文件作为输入,那么FNR的值会在处理每个数据文件时被重置,NR的值则会继续计数直到处理完所有的数据文件。
2、自定义变量
gawk自定义变量的名称由任意数量的字母、数字和下划线组成,但不能以数字开头。而且,其变量名区分大小写。
在脚本中给变量赋值
在gawk脚本中给变量赋值与给shell脚本中的变量赋值一样,都使用赋值语句。
gawk '
BEGIN{
test1="测试……"
print test1
}'
也可以保存数值或文本值:
gawk '
BEGIN{
test1="测试……"
print test1
test1=89
print test1
}'
还可以处理数学算式:
gawk 'BEGIN{x=7; x=x *9 + 10; print x}'
在命令行中给变量赋值
可以在不修改脚本代码的情况下改变脚本的行为。
BEGIN{FS=","}
{print $n}
gawk -f test.sh n=3 test2.txt
通过上述命令,可以显示文件中的第3个字段(n=3)。
使用命令行参数来定义变量值会产生一个问题:在设置过变量之后,这个值在脚本的BEGIN部分不可用。
BEGIN{print "开始值是",n; FS=","}
{print $n}
gawk -f test.sh n=3 test2.txt
使用 -v 选项解决该问题,它允许在BEGIN部分之前设定变量。它必须放在脚本代码之前。
gawk -v n=3 -f test.sh test2.txt
二、数组
gawk使用关联数组来提供数组的功能。与数字型数组不同,关联数组的索引可以是任意文本字符串,它用各种字符串来引用数组元素,每个索引字符串都必须能够唯一地标识出分配给它的数组元素。就跟其它语言中的哈希表、字典类似。
1、定义数组变量
使用标准赋值语句定义数组变量。
格式:var[index] = element
var:变量名;index:关联数组的索引值;element:数组元素值
gawk 'BEGIN{
capital["中国"] = "北京"
print capital["中国"]
}'
2、遍历数组变量
在gawk脚本中遍历关联数组,使用for语句的一种特殊形式。
for {var in array}
{
statements
}
此for语句会在每次循环时将关联数组array的下一个索引值赋给变量var,然后执行一遍statements。变量var中存储的是索引而不是数组元素值。
gawk 'BEGIN{
var["a"] = 10
var["h"] = 190
var["k"] = 78
var["t"] = "hello"
for (test in var)
{
print "索引:",test," - 值:", var[test]
}
}'
如下所示,索引值没有固定的返回顺序。
3、删除数组变量
从关联数组中删除数组元素要使用一个特殊的命令:
delete array[index]
delete命令会从关联数组中删除索引值及其相关的数组元素值。
gawk 'BEGIN{
var["a"] = 10
var["h"] = 190
var["k"] = 78
var["t"] = "hello"
for (test in var)
{
print "索引:",test," - 值:", var[test]
}
delete var["k"]
print "*****"
for (test in var)
{
print "索引:",test," - 值:", var[test]
}
}'
三、使用模式
gawk支持几种类型的匹配模式来过滤数据记录。比如,关键字BEGIN和END可以在读取数据流之前或之后执行命令的特殊模式。
1、正则表达式
可以使用基础正则表达式(BRE)或扩展正则表达式(ERE)来筛选数据。
在使用正则表达式时,它必须出现在与其对应脚本的左花括号前。
# 匹配含有字符串“11”的数据
gawk 'BEGIN{FS=","} /11/{print $1}' test2.txt
#匹配用作字段分隔符的逗号
gawk 'BEGIN{FS=","} /,d/ {print $1}' test2.txt
2、匹配操作符
匹配操作符(~)是一个很强大的工具,可以将正则表达式限制在记录的特定数据字段。可以指定匹配操作符、数据字段变量以及要匹配的正则表达式。
$1 ~ /^data/:此表达式会过滤出第一个数据字段以data开头的所有记录。
gawk 'BEGIN{FS=","} $2 ~ /^data3/{print $0}' test2.txt
匹配第2个数据字段要以“data3”开头的数据。
可以用它在文件中搜索特定的数据元素。
gawk -F: '$1 ~ /csb/{print $1, $NF}' /etc/passwd
上面的脚本命令会在第一个数据字段中查找文本“csb”,如果匹配成功,则打印出第一个数据字段和最后一个数据字段。
也可以使用 ! 符号来排除正则表达式的匹配:
$1 !~ /expression/
gawk -F: '$1 !~ /^csb/{print $1,$NF}' /etc/passwd
匹配第一个数据字段不是以“csb”开头的数据, 如果匹配成功,则打印出第一个数据字段和最后一个数据字段。
3、数学表达式