实现一个检索功能,要求如下:
需要处理的文件为listbook.txt
内容为:
mona 70 77 85 83 70 89
john 85 92 78 94 88 91
andrea 89 90 85 94 90 95
jasper 84 88 80 92 84 82
dunce 54 80 60 60 61 62
ellis 90 98 89 96 96 92
第一字段和第二字段分隔符为制表符,之后分隔符为空格.
实现的功能为,运行脚本后,要求输入一个字符串;输入后按回车键,如果与第1字段内容匹配,则输出该行第二字段以后的内容。
输入特殊字符串,如exit,quit,x,q等时退出执行
代码如下:
BEGIN { FS =" ";OFS=" "
printf("Enter a name: ")
}
FILENAME == "testbook.txt" {
entry[$1] = $2
next
}
$0 ~ /^(quit|exit|[qQ]|[xX])$/ {
exit }
$0 != "" {
if ($0 in entry){
print entry[$0]
}else
print $0 " not found"
}
{
printf("Enter another name (q to quit:")
}
脚本保存为awklookup
运行脚本:
awk -f awklookup testbook.txt
运行结果:
运行脚本后,输入了mano,没有检索到;输入john,检索到并输出;输入q,退出了执行。
脚本分析:
BEGIN中通过next语句完成将testbook.txt文件所有行读出,存入数组。
之后的代码没有可读取的内容,等待标准输入给出内容,其中最后的代码模块输出提示,要求输入。
当输入字符串并按回车时,完成了一次标准输入。awk将它作为一行来处理,代码中体现的就是使用了变量$0。
使用in语句判断$0是否是关联数组中的元素之一,否则输出其值。
这里注意,运行脚本 文件名最后,还有一个“-”
awk允许同时处理2个文件或一个文件+标准输入,这里就实现了文件+标准输入的用法。
split()函数
内建函数split()能够将任何字符串分解到数组的元素中。这个函数对于从字段中提取“子字段”是很有用的。语法如下:
n=split(string,array,separator)
string是要被分解到名字为array的元素中的输入字符串。数组的下表从1开始到n,n即为数组中元素的个数。元素根据指定的separator分隔符分解。
没有指定分隔符,使用字符安分隔符(FS)。separator可以是一个完整的正则表达式,而不仅仅是单个字符。
举例:使用上面的例子中的文本testbook.txt,只输出第二字段第2子字段。
awk -F " " '{n = split($2,subarr1," ");print subarr1[2wq]}' testbook.txt
运行结果:
-F设置了制表符作为分隔符,所以每行awk识别为2列数据,第一列是英文,第二列是由数字和空格组成的字符串,比如:"70 77 85 83 70 89",split用第二列数据作为分隔目标,空格作为分隔符,输送到数组subarr1中,第二个元素的数据就是77。
利用这个函数可以实现某种转换,例如将罗马数字转换成阿拉伯数字。
n=split("I,II,II,IV,V,VI,VII,Viii,IX,X",numbers,",")
上面说过,下标是从1开始,这样利用下标跟罗马数字一一对应 了。
类似的,可以将阿拉伯格式的月日年,转换为英文的月日年
删除数组元素非常简单,awk提供了一个删除一个元素的语法,如下:
delete arrary[subscript]
删除数组arrary下标为subscript的元素。
此时,使用in语句检测subscript将返回假设。这与元素赋值一个空值是不同的。
再来一个例子,要求如下:
每行有多个单词,将每行每个单词的首字母合并
样本文件Sample内容如下:
The USGCRP is a compreshensive
research effort that includes applied
as well as basic research.
The NASA program Mission to Planet Earch
represents the principal space-based component
of the USGCRP and includes new initiatives
such as EOS and Earthprobes.
缩写说明文本acronyms内容如下:
USGCRP U.S Globa_ Change Research Program
NASA National Aeronautic and Space Administration
EOS Earth Observing System
脚本awkkro将实现,读取Sample内容,如包含缩写,将翻译为完整拼写。
代码如下:
awk '
FILENAME == "acronyms" {
split($0,entry," ")
acro[entry[1]] = entry[2]
next
}
/[A-Z]/ {
for (i = 1; i <= NF ; i++)
if ( $i in acro ) {
$i =acro[$i] "(" $i ")"
}
}
{
print $0
}' acronyms S*
运行结果:
The U.S Globa_ Change Research Program(USGCRP) is a compreshensive
research effort that includes applied
as well as basic research.
The National Aeronautic and Space Administration(NASA) program Mission to Planet Earch
represents the principal space-based component
of the U.S Globa_ Change Research Program(USGCRP) and includes new initiatives
such as Earth Observing System(EOS) and Earthprobes.
略作说明:
现将acronyms内容读入存储数组备用。
读取Sample文件,对含有大写字母的行执行对每个字段与数组值比对,存在则进行转换。
代码中in作为一个操作符,判断变量是否在数组中存在。
多维数组
awk不支持多维数组,但它为下标提供了一个语法来模拟引用多维数组。
file_array[NR,i] #变量可以是一个数字
例子:
{
for(i=1;i<=NF;i++)
{
file_array[NR,i]=$i
}
}
END{
print file_array[3,3]
}
运行脚本:
awk -f awkmutiarray stu.txt
例子中END模块输出3行3列的内容。
看上去是个二维数组,但是实际是一个线性数组。它被默认转换。
实际被转换为“3\0343”,其中\034是一个不显示的字符,下标分隔符默认定义为034
模拟二维数组的后果是数组越大,访问元素就越慢。使用时慎重。
多维数组也支持测试数组成员,但是必须将下标用圆括号括起来,例如:
if ( (3,3) in array )
{
..
}
系统变量的数组
ARGV
这是一个命令行参数的数组,不包括脚本本身和任何调用awk指定的选项。
这个数组的元素的个数可以从argc中获得。
数组中第一个元素的下标是0最后一个下标是(ARGC-1)
这个跟awk中的其他数组不同。
ENVIRON
一个环境变量数组,书中每个元素是当前环境变量的值,而其下标是环境变量的名字。
例子:输出参数的例子
BEGIN{
for (x=0;x { print ARGV[x] } print ARGC } awk -f awkargv stu.txt n=44 fff 输出结果: awk stu.txt n=44 fff 4 最后一个是参数数量,第一个是命令本身。 一般参数不会少于2个。 如果在脚本中调用了awk,命令行参数将传递给给脚本,而不是awk。 您必须将shell脚本的命令行参数,传递给shell中的awk。例如,可以用“$*”将脚本中所有命令行参数传递给iawk。 例子: awk ' BEGIN{ ... } ' $* 一个实际的用法,在BEGIN过程中,用政策表达式来测试命令行参数。 例子:测试除第一个参数外的其他所有参数为整数 BEGIN { for (x=1;x if ( ARGV[x] !~ /^[0-9]+$/ ) { print ARGV[x], "is not an integer." exit 1 } } 如果参数中包含非数字的字符,程序键给出提示并退出。 再看一个例子: awk ' BEGIN { FS = "," if ( ARGC > 2) { name = ARGV[1] delete ARGV[1] }else{ while ( ! name ) { printf("ENTER a name:") getline name < "-" } } } $1 ~ name { print $1, $NF }' $* phones.data 文件内容: 通过测试变量ARGC来看参数个数是否大于2.通过指定$* 可以将shell 命令行所有的参数传递给awk的命令行。如果提供了参数,假设第二个参数是ARGV[1]是我们所需要的,那么将它赋给变量name。 然后将这个参数从数组中删除。如果命令行上提供的这个参数不是var=value形式,它将在随后被解释为文件名。如果提供了另外的参数,则将会被解释为可选的电话号码数据库的文件名。如果参数个数小于2,那么我们将提示输入名字。
留言与评论(共有 0 条评论)
“”