awk命令

AWK: linux中的AK47,突突突~

言归正传,awk命令的最基本功能是在文件或字符串中基于指定规则浏览和抽取信息。awk抽取信息后,才能进行其他文本操作。几乎所有包含awk命令的脚本都结合了sed和grep来对文本进行处理。

几种命令格式

1、命令行格式:
awk [-F field-separator] ‘command’ input-file(s)

[-F 域分隔符] 是可选项,缺省分隔符为空格。

2、插入awk文件
awk -f awk-script-file input-files

-f 选项指明文件在 awk-script-file中的awk脚本,input-files是使用awk进行浏览的文件名。

模式和动作

任何awk语句都由模式和动作组成。在一个awk脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。

模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段BEGIN和END。使用BEGIN语句设置计数和打印头。 BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文件开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志。如果不特别指明模式,awk总是匹配或打印行数。

实际动作在大括号{ }内指明。动作大多数用来打印,但是还有些更长的代码诸如 if 和循环(looping)语句及循环退出结构。如果不指明采取动作, awk将打印出所有浏览出来的记录。

域和记录

awk执行时,其浏览域标记为$1,$ 2 … $ n。这种方法称为域标识。使用这些域标识将更容易对域进行进一步处理。

使用$1 , $3表示参照第1和第3域,注意这里用逗号做域分隔。如果希望打印一个有5个域的记录的所有域,不必指明$1 , $2 , $3 , $4 , $5,可使用$0,意即所有域。awk浏览时,到达一新行,即假定到达包含域的记录末尾,然后执行新记录下一行的读动作,并重新设置域分隔。注意执行时不要混淆符号$和shell提示符$,它们是不同的。

内置变量

awk内置变量
这里写图片描述

  • ARGC支持命令行中传入awk脚本的参数个数。ARGV是ARGC的参数排列数组,其中每一元素表示为ARGV[ n ],n为期望访问的命令行参数
  • ENVIRON 支持系统设置的环境变量,要访问单独变量,使用实际变量名,例如ENVIRON [“EDITOR”] =“Vi”
  • FILENAME支持awk脚本实际操作的输入文件。因为awk可以同时处理许多文件,因此如果访问了这个变量,将告之系统目前正在浏览的实际文件
  • FNR支持awk目前操作的记录数。其变量值小于等于NR。如果脚本正在访问许多文件,每一新输入文件都将重新设置此变量
  • FS用来在awk中设置域分隔符,与命令行中 -F 选项功能相同。缺省情况下为空格。如果用逗号来作域分隔符,设置FS = “,”
  • NF支持记录域个数,在记录被读之后再设置
  • OFS允许指定输出域分隔符,缺省为空格。如果想设置为#,写入OFS=”#”
  • ORS为输出记录分隔符,缺省为新行(\ n)
  • RS是记录分隔符,缺省为新行( \ n )

错误很可能是以下原因造成

• 确保整个awk命令用单引号括起来。
• 确保命令内所有引号成对出现。
• 确保用花括号括起动作语句,用圆括号括起条件语句。
• 可能忘记使用花括号,也许你认为没有必要,但a w k不这样认为,将按之解释语法。

示例:

1、awk读每一条记录。因为没有模式部分,只有动作部分{print $0}(打印所有记录),也可以使用其他域{print $1,$3},这个动作必须用花括号括起来:

awk ‘{print $0}’ grade.txt

2、利用 BEGIN 和 END 打印报告头和结束尾:

awk ‘BEGIN{print "Name:\n--------"} {print $1} END{"---------\n end-of-name"}’ grade.txt

3、如果在命令行并没有输入文件input-files,那么awk在打印报告头之后会期待从键盘输入,ctrl+d 结束输入。

4、正则表达式和条件操作符
这里写图片描述
为使一域号匹配正则表达式,使用符号‘~’后紧跟正则表达式,也可以用if语句。awk中if后面的条件用()括起来:

awk '{if($4~/jerry/) print $0}' grade.txt

匹配记录找到时,如果不特别声明,awk缺省打印整条记录:

awk '$0 ~ /Jerry/' grade.txt

5 、精确匹配:为精确匹配48,使用等号==,并用双引号括起条件。例如$ 3==“48”,这样确保只有48序号得以匹配,其余则不行:

awk '$3=="48" {print $0}' grade.txt

6、不匹配:

awk '{if($3!~/jerry/) print $0}' grade.txt

7、要快速查看记录个数,应使用NR。使用NR将打印输入文件的记录个数。print NR放在END语法中。

awk 'END {print NR}' grade.txt

awk '{print NF,NR,$0} END {print FILENAME}' hello

8、NF的一个强大功能是将变量$ PWD的返回值传入awk并显示其目录。这里需要指定域分隔符/。另一个例子是显示文件名。

echo $PWD | awk -F/ '{print $NF}'
//输出 learngit
echo "/e/learngit/hello.txt" | awk -F/ '{print $NF}'
//输出 hello.txt

9、设置输入域到域的变量名:在awk中,设置有意义的域名是一种好习惯,在进行模式匹配或关系操作时更容易理解。一般的变量名设置方式为name = $n,这里name为调用的域变量名,n为实际域号。分号用来风格awk命令。

awk '{name=$1;belts=$4;if(belts~/Yello/)print name" is belt"belts.}' grade.txt

10、域值比较:

  • 在BEGIN中给变量名赋值。
  • 在关系操作中使用实际数值。
  • 通常在BEGIN部分赋值是很有益的,可以在awk表达式进行改动时减少很多麻烦。
  • 使用关系操作必须用圆括号括起来。
awk 'BEGIN {BASELINE="28"}{if($6<BASELINE) print $0}' grade.txt

11、修改数值域以及文本域:

//修改数值域
awk '{if($1=="jerry") $5=$5+1;print $1,$5,$6}' grade.txt
//修改文本域并打印全部
awk '{if($1=="jerry") $1="Hello,jerry!"; print $1}' grade.txt
//修改文本域,只打印修改后的文本
awk '{if($1=="jerry") {$1="Hello,jerry!"; print $1}}' grade.txt

12、创建新的输出域:在awk中处理数据时,基于各域进行计算时创建新域是一种好习惯,例如原先不存在的域 $8。当然可以创建新域,并赋给其更有意义的变量名diff。

awk 'BEGIN{ print "name\t different"}{if($6<$7) {$8 = $7-$6;print $1,$8}}' grade.txt
awk 'BEGIN{ print "name\t different"}{if($6<$7) {diff = $7-$6;print $1,diff}}' grade.txt

13、文件某一域数值统计:

// 打印过程和结果
awk '(tot+=$2); END{print "total number is:"tot}' grade.txt
// 或者只打印结果,而不打印过程
awk '{(tot+=$2)}; END{print "total number is:"tot}' grade.txt

14、文件长度相加:想快速查看所有文件的长度及其总和,但要排除子目录,使
用ls -l命令,然后管道输出到awk,awk首先剔除首字符为d(使用正则表达式)的记录,然后将文件长度列相加,并输出每一文件长度及在END部分输出所有文件的长度。

ls -l | awk '/^[^d]/ {print $9"\t"$5} {tot+=$5} END {print "total KB:"tot}' 

附:awk操作符
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值