awk应用技巧

12 篇文章 1 订阅
4 篇文章 0 订阅

awk的基本用法

awk是一个灵活强大的文本处理工具,其基本使用命令格式如下:

awk [ -F fs ] [ -v var=value ] ‘pattern {action}' [ file | - ... ]

上述awk命令包含三个基本部分:

  • 选项部分。包括-F选项指定分割字符传,可以是正则表达式。当awk处理每一行时,会按照分割字符串将一行分割成若干域。-v选项则用于赋值变量,这些赋值在'pattern {action}'执行之前完成,并且在'pattern {action}'中可访问。
  • 'pattern {action}'部分。这部分是awk最强大地方。在一个awk命令中可以带一个或多个'pattern {action}',每一个'pattern {action}'的作用是:当awk匹配到其中的pattern部分时,执行其中的action部分。而action部分则可以支持类似C语言语法的一系列复杂语句,如if...else条件判断、while/for循环等。对于很复杂的'pattern {action}',还可以把他们放入一个单独的文件中,这样的文件就叫做awk程序文件,然后在awk命令中通过-f调用。
awk [ -F fs ] [ -v var=value ] [-f progfile] [ file | - ... ]
  • 目标文件部分。awk的处理对象可以是一个或多个文本文件,也可以是标准输入。"-"就表示标准输入,如果什么都不指定,默认也是标准输入。

当给定文本文件或者标准输入后,awk会逐行进行处理。特殊变量NR是一个计数器变量,表示当前处理的行数。还有一个特殊的计数器变量FNR,表示的是当前文件中当前正在处理的行数。当只处理一个文件时,FNR和NR是一样的;但是当处理多个文件是,NR是累计的,而FNR是针对每个文件计数的。

对于每一行,awk会根据分割字符串进行分割。分割后产生若干个域。特殊变量FR表示当前行的域个数。分割形成的域分别用$1,$2,$3,...来表示。注意$0表示的是整行。

以下通过一些例子说明具体的用法。

 

下面这个例子演示-v的用法。通过-v指定var1,在print里面就可以直接访问。在这个例子中,并没有指定pattern。这种情况下awk默认就是总能匹配,因此总是执行action。

echo "" | awk -v var1=value1 '{print var1}'
value1

下面这个例子演示分割字符串的用法。通过指定输入为"-",awk会从标准输入读入进行处理,这里也就是处理"key=value"。事实上也可以省略"-",因为默认就是从标准输入读入。在这里指定了分割符为"=",因此输入行的"key=value"应该被分割成两个域key和value。在awk中通过NF来得到域个数,通过$1和$2来得到第一个域和第二个域。

echo "key=value" | awk -F '=' '{print NF,$1,$2}' -
2 key value

下面的例子演示多个文件的处理,以及FNR和NR的不同之处。先创建两个文本文件test1.txt和test2.txt,然后再执行awk命令。在结果中可以看到NR是一直累加的,而FNR是每个文件内累加的。

This is line 1 in file 1.
This is line 2 in file 1.
This is line 1 in file 2.
This is line 2 in file 2.
awk '{print FNR,NR,NF}' test1.txt test2.txt
1 1 7
2 2 7
1 3 7
2 4 7

除了前面提到的FNR,NR,NF等特殊变量,awk还支持其它的特殊变量,详见下。在action部分灵活运行这些特殊变量,可以起到事半功倍的效果。

       CONVFMT
              在打印数值时的转换格式,默认为 %.6g

       FS     分割符

       NF     当前记录(行)中的域数

       NR     当前记录序号

       FNR    当前文件中的当前记录序号

       FILENAME
              当前输入文件名

       RS     输入记录分割符,默认为换行

       OFS    输出域分割符,默认为空格

       ORS    输出记录分割符,默认为换行

       OFMT   数值输出格式,默认为 %.6g

       SUBSEP 分割多个子脚本

       ARGC   参数个数

       ARGV   参数数组

       ENVIRON
              环境变量数组

 

在前面的例子中,action部分用到了print函数。这时awk的内置函数,用于打印参数列表。除了print之外,awk也只printf函数。printf函数的用法与C语言中的printf函数类似,允许进行输出格式化。以下例子应用awk将数字按照指数格式进行打印输出。

echo 120000000 | awk '{printf("%s=%.2e",$0,$0)}'
120000000=1.20e+08

awk还支持一些其它的内置函数,包括数学函数,如log、exp、sqrt、sin、cos、rand等;字符串操作函数,如length、index、split、sub、toupper、tolower等。GNU awk (gawk)还支持更多的内置函数,完整信息可参考https://www.gnu.org/software/gawk/manual/gawk.html#Calling-Built_002din

 

下面的例子演示了内置函数length的用法:

echo "Hello world" | awk '{printf("Length of the string \"%s\" is: %d",$0,length($0))}'
Length of the string "Hello world" is: 11

前面的例子中,'pattern {action}'中的pattern部分都是空的,因此awk默认就都能匹配。实际上awk可以支持复杂的正则表达式匹配。下面的例子中,假设需要统计"line"在文本文件test1.txt中出现的次数和行数。为此就需要逐行匹配"line"。而匹配到"line"后,action中需要记录行号和次数。测试文本文件test1.txt和awk命令分别如下。

This is line 1 in file 1.
This is line 2 in file 1.

Hello world
This is last line.
awk 'BEGIN{n=0} /line/ {lines[n++]=NR} END {for(i=0;i<n;i++) printf "@Line %d\n",lines[i]}' test1.txt
@Line 1
@Line 2
@Line 5

awk程序脚本

当处理程序比较复杂时,通常将处理程序写入独立的程序文件以供调用,程序文件的一般1以.awk作为后缀名。

 

假设有以下文本文件numbers.txt

56 32 48 100
5 7 80 90
4 1 0 120

现在想利用awk计算出每行的和并添加到每行末尾,计算出每列的和放到每列下面,然后输出美观的结果。为了实现这个功能,编写awk程序sum.awk如下。

#!/usr/bin/awk
BEGIN {
max_col = 0
}
{
line_sum = 0
for (i = 0; i < NF; i++) {
        f = i+1
        printf "%4d ",$f
        line_sum += $f
        col_sum[i] += $f
}
if (max_col < NF) max_col = NF
printf "    |  %d\n",line_sum
}
END {
for (i = 0; i < max_col; i++) {
    printf "-----",col_sum[i]
}
printf "\n"
for (i = 0; i < max_col; i++) {
    printf "%4d ",col_sum[i]
}
}

通过awk工具运行sum.awk程序,可以得到如下结果。结合代码很好理解。

awk -f sum.awk numbers.txt
  56   32   48  100     |  236
   5    7   80   90     |  182
   4    1    0  120     |  125
--------------------
  65   40  128  310

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值