awk相比于sed的话是用来统计的用的多,sed是用来修改删除文本的
NF指的是字段的个数,所以$NF指的是最后一个字段
文本处理awk
awk简介
awk是一种编程语言,用于在linux、unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux、unix下的强大编程工具。它在命令行中使用,但更多是作为脚本来使用。
awk的处理文本是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一个字母。
awk两种形式语法格式
awk [option] ‘commands’ filenames
awk [option] -f awk-script-file filenames
options
-F 定义输入字段分隔符,默认的分隔符是空格或制表符(tab)
例:
定义分隔符为冒号
awk -F":" '{print $1}' 文件名
commands
行处理前 BEGIN{}
行处理 {}
行处理后 END{}
awk 'BEGIN{print 1/2} {print "ok"} END{print "-----------"}' t.txt
这里为什么显示3个ok,因为awk是逐行处理。t.txt文件里有三行,每行执行一次行处理 {}。所以就有了3个ok
BEGIN{}通常用于定义一些变量,例如BEGIN{FS=":";OFS="---"}
如下在begin中用FS定义读入分隔符
awk 'BEGIN{FS=":"} {print $1}' t.txt
用OFS设置输出分隔符(默认是空格)(print 里面作为分隔的逗号,被映射为OFS变量,所以你懂了)
awk 'BEGIN{FS=":";OFS="---"} {print $1,$2}' t.txt
awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕
awk命令格式
awk ‘pattern’ filename 纯按正则表达式寻找匹配行
awk ‘{action}’ filename 纯按行执行下来,每行都执行action
awk ‘pattern {action}’ filename先按正则表达式进行匹配,再将匹配结果送到action里处理
以上的pattern {action}都属于行处理 {}的部分(BEGIN{} {} END{})
记录与字段相关内部变量man awk
$0: awk变量$0保存当前记录的内容
NR:显示行号(记录总的行数,即把awk处理的所有文件结果总的行数)
FNR:显示行号(分文件显示行数)
NF 当前行的字段数(列数)$NF自然就表示最后一列
FS 输入字段的分隔符
下面是将冒号和空格都设置为分隔符,冒号和空格都能分隔
awk -F'[ :\t]' '{print $1,$2,$3}' 文件名
awk 'BEGIN{FS=":";OFS="---"} {print $1,$2}' t.txt
OFS 输出字段分隔符
RS 读入换行符(默认回车)
ORS输出换行符(默认回车)
区分:
字段分隔符:FS,OFS 默认为空格或制表符
记录分隔符(行分隔符):RS,ORS 默认换行符(回车)
格式化输出
print函数
变量一定要放到引号外面
\t是制表符tab
date |awk '{print "Month:" $2 "\nYear:" $NF}'
awk -F: '{print "username is:" $1 " \t uid is:"$3}' 文件名
awk -F: '{print "\tusername and uid:"$1,$3"!"}' 文件名
printf函数
和C一样
%s 字符类型
%d 数值类型
%f 浮点型
占15字符
-表示左对齐,默认的是右对齐
printf默认是没有换行的,需要主动加\n
awk -F: '{printf"%-15s %-10s %-15s\n",$1,$2,$3}' 文件名
awk -F: '{printf"|%-15s|%-10s|%-15s|\n",$1,$2,$3}' 文件名
awk模式和动作
任何awk语句都由模式和动作组成。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文本开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态。
模式可以是
正则表达式
匹配记录(整行):
awk '/^alice/' 文件名
awk '$0~/^alice/' 文件名 与前一句的功能一致,也就是在这一行中匹配alice开头的行
awk '!/alice/' 文件名
awk '$0!~/^alice/' 文件名 匹配不是alice开头的行
匹配字段:匹配操作符(~ !~)
awk -F: '$1~/^alice/' 文件名 匹配开头是alice的行
awk -F: '$NF!~/bash$/' 文件名 匹配结尾不是bash的行
比较表达式
比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关系运算符,用于比较数字与字符串。
关系运算符
还有三元运算符 ? : 和C一样
< <= == != >= >
例:
加引号的表示比较的字符串,不加表示比较的是数字
awk -F: '$3 == 0' 文件名
awk -F: '$3 == "alice" 文件名
条件表达式
最好是按第三条和第四指令写 if() {} else {}
{}内的多条命令用;分隔
awk -F: '$3>300{print $0}' 文件名
awk -F: '{if($3>300) print $0}' 文件名
awk -F: '{if($3>300) {print $0}}' 文件名 前三条指令的功能是一致的,有{}可以包含多条指令
awk -F: '{if($3>300) {print $3} else{print $1}}' 文件名
算术运算:+-*/%^(幂2^3)
可以在模式中执行计算,awk都将按浮点数方式执行算术运算
awk -F '$3* 10 >500' 文件名
awk -F '{if($3*10>500){print $0}' 文件名
逻辑操作符
&& || !
范围模式
awk '/Tom/,/Suzanne/' 文件名
ps:
设置分隔符一个或多个都看成一个
这一类方便处理文本内容如:111 222::333::: 444:555:666
这样的
也就是用了正则表达式
awk -F"[ :]+" 'print NF' t.txt 注意冒号前有空格,所以最后+就是1个或连续多个冒号或空格都看成一个分隔符
设置分隔符一个
awk -F"[ :]" 'print NF' t.txt
awk用数组
awk里面没有shell里面的普通数组,awk里面的全是关联数组
sort命令排序
AWK使用外部变量的三种方法
ps:介绍几个函数
length(变量) 计算变量的长度
int(变量) 取出字符串的整数部分 比如int(20%)=20
为何会有awk使用外部变量的问题?
看下面这个例子:
var="bash"
echo "unix script" |awk "asd$var"
会发现awk根本拿不到这个var变量
需要用下面的方式使用
方式1
在双引号内给外部变量套上\" \"
echo "unix script" |awk "asd\"$var\""
方式2
在单引号内使用外部变量 给变量套上"’" “’”
echo "unix script" |awk 'asd"'"$var"'"'
方式3
awk参数-v(建议用)
echo "unix script" |awk -v x=$var 'asd,x'