一,awk简介
awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。
awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。
二,awk的语法格式
**awk [options] 'commands' filenames**
awk中使用最多的选项-F的含义是定义输入字段分隔符,默认的分隔符是空格或制表符(tab)
awk中commands部分可以分为三段,分别为**行处理前、行处理、行处理后**。下面的例子:
awk 'BEGIN{print 1/2} {print "ok"} END{print"........"}' /etc/hosts,如果hosts文件中有3行,那么执行这条命令的输出是:
0.5
ok
ok
ok
.........
## awk的命令格式
awk ‘pattern’ filename 示例:awk -F: ‘/root/’ /etc/passwd
awk '{action}' filename 示例: awk -F: '{print $1}' /etc/passwd
awk 'pattern {action}' filename 示例: awk 'BEGIN{FS=":"} /root/{print $1, $3}' /etc/passwd
注意上面命令中-F: 等价于FS=":"
三、awk工作原理
awk -F: '{print $1, $3}' /etc/passwd
第一步:awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符结束
第二步:行被:(默认为空格或制表符)分解为字段(或域),每个字段存储在已编号的变量中,从$1开始。awk如何知道用空格来分隔字段的?因为有一个内部变量FS来确定字段分隔符。初始时,FS赋为空格。
第三步:awk打印字段时,将以设置的方法使用print函数打印,awk在打印的字段间加上空格,因为$1,$3之间有一个逗号。逗号比较特殊,它映射为另一个内部变量,称为输出字段分隔符OFS,OFS默认为空格。
第四步:awk输出之后,将从文件中获取另一行,并将其存储在$0,覆盖原来的内容,然后将新的字符串分隔成字段进行处理。该过程将持续到所有行处理完毕。
四、awk内部变量
$0: awk变量$0保存当前记录的内容 #awk -F: '{print $0}' /etc/passwd
NR: 总记录的编号
FNR: 当前输入文件的记录编号
NF: 当前记录的字段数目
FS: 输入字段分隔符,默认情况下是空格或制表符
OFS: 输出字段分隔符
RS: 输入记录分隔符,默认为换行符
ORS: 输出记录分隔符
awk -F: 'BEGIN{ORS=" "} {print $0}' passwd > passwd1 将文件passwd中的每一行输出到passwd1中,并且每行之间都有一个空格,因为修改了ORS的默认值。
五、awk格式化输出
## printf函数
awk -F: ‘{printf "%-15s %-10s %-15s\n", $1,$2,$3}’ /etc/passwd
注意%s是字符类型,%d是数值类型,%f是浮点类型。15指的是占15字符。-表示左对齐,默认是右对齐。需要注意的是printf默认不会在行尾自动换行,加上\n后就可以进行换行了。
## awk的模式和动作
任何awk语句都由**模式**和**动作**组成。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览器动作之前,之后文本浏览动作依据输入文本开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态。
**匹配记录(整行):**
awk '$0 ~ /^alice/' /etc/passwd 输出匹配行
awk '$0 !~ /^alice/' /ect/passwd 输出不匹配行
**匹配字段:匹配操作符(~ !~)**
awk -F: '$1 ~ /^alice/' /etc/passwd 输出第一个字段是alice的行
awk -F: '$NF !~ /bash$/' /etc/passwd 输出最后一个字段不是bash的行
**需要注意的是,模式中是可以使用关系运算符的,比如<、<=、==、!=等,条件表达式也是可以的**
awk -F: 'if(条件) {动作} else{动作}' /etc/passwd
**模式中也是可以有算术运算和逻辑操作符(&&,||,!)和符合模式**
六、awk脚本编程
## if格式
{if(表达式) {语句;语句;....}else{语句}}
## while循环
awk -F: '{i=1; while(i<=NF){print $i; i++}}' /etc/passwd
上面命令的含义是打印passwd文件中每一行的每一列。
awk -F: '/^root/{i=1; while(i<=NF){print $i; i++}}' /etc/passwd
上面命令的含义是打印passwd文件中以root开头行的每一列。
## for循环
awk 'BEGIN{for(i=1; i<=5; i++){print i}}' C风格的
## 数组
awk中的数组默认支持关联数组。
数组遍历的时候我们使用索引遍历。
awk -F: '{username[x++]=$1 END{for(i in username) {print i,username[i]} }' /etc/passwd
注意:变量i是索引。
七、awk使用外部变量的方法
第一种情况,在双引号的情况下使用外部变量
第二种情况,使用awk的参数-v(建议使用)