在Linux/Unix系统中,awk是一个功能强大的编辑工具,逐行读取输入文本,默认以空格或tab键作为分隔符分隔,并按模式或者条件执行编辑命令。
awk信息的读入也是逐行指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,可以在无交互的情况下实现相当复杂的操作,被广泛应用于shell脚本,完成各种自动化配置任务。
第一步:执行BEGIN{action;...}语句块中的语句
第二步:从文本或标准输入(stdin)读取一行,然后执行pattern{action;...}语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{action;...}语句块
BEGIN语句块在awk开始从输入流读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。
END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句 块中完成,它也是一个可选语句块。
pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{print},即打印 每一个读取到行,awk读取的每一行都会执行该语句块。
sed命令常用于一整行的处理,而awk比较倾向于将一行分为多个“字段”然后再进行处理,切默认情况下字段的分隔符为 空格或TAB键。
awk 选项 ‘模式或条件 { 操作}’ 文件1 文件2
-F “分隔符”指明输入时用到的字段分隔符,默认的分割符是若干个连续空白符。
用单引号:'模式或条件{条件}'
{ }外指定条件 {}内指定操作 用逗号指定连续的行,用 || 指定不连续的行,&&表示“且”
内建变量,不能用双引号括起来,不然系统会把它当成字符串。
$0: 当前处理的行的整行内容
$n: 当前处理行的第n个字段 (第n列)
NR: 当前处理的行的行号(序数)
NF:当前处理的行的字段个数。
$NF代表最后一个字段。
FS:列分隔符。指定每行文本的字段分隔符,输入内容的的分隔符。默认为空格或制表位。与“-F”作用相同 用-F可以不 加单引号,必须用=“”
OFS:输出内容的列分隔符
FILENAME:被处理的文件名
RS:行分隔符 。 awk从文件读取资料时,将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录进行 处理。预设值是“\n”换行。
awk '{print}' 默认{print}前有一个1,0是不打印
awk '{print $1}' 文件名 取所有行的第一列(因为是对行生效)
awk '{print NR,$0}' 文件名 打印行号和内容
awk ' NR==3{print}' 文件名 打印第三行
awk 'NR==3,NR==5{print}' 文件名 打印三到五行
awk 'NR==3;NR==5{print}' 文件名 打印第三和第五行
awk '(NR>=4)&&(NR<+9){print}' 文件名 打印第四到第九行内容(正则表达方式)
awk ' NR%2==0{print}' 文件名 取偶数行
awk ' NR%1==0{print}' 文件名 取奇数行
awk '{getline;print $0}' 文件名 取偶数行
awk '{print $0;getline }' 文件名 取奇数行
求幂:awk 'BEGIN{print 3**2}' 三的二次方
awk 'BEGIN{print 3^2}' 三的二次方
getline工作工程
当getline左右无重定向符号(“<”)或者管道符号(“|”)时,awk首先读取的事第一行,而getline获取的是光标跳转至下 一行的内容。
ls | awk '{getline line; print $0,line;}' 作用等同于ls
awk '/^root/{print}' /etc/passwd 打印目录下以root开头的行
awk '/bash$/{print}' /etc/passwd 打印目录下以bash结尾的行
格式:awk 'BEGIN{...};{...};END{...} '文件名
处理过程: 1、在awk处理指定的文本之前先要执行BEGIN模式里的命令操作
2、中间的{...}是真正用于处理文件的命令操作
3、在awk处理完文件后才会执行END{...}
awk 'BEGIN{x=1};{x++}END{print x}' 文件名 循环行数进行+1
awk -F: '{print $1}' /etc/passwd 以冒号为分隔符打印/etc/passwd的第一列
awk -F: '{print $2}' /etc/passwd 以冒号为分隔符打印/etc/passwd的第二列(密码占位符)
-v的用户:变量赋值(针对分隔符)
awk -v FS=':' -v OFS='==' '{print $1,$3}' /etc/passwd 第一和第二列,如果一到三只能$1,$2,$3 ▲
echo $PATH | awk -v RS=':' '{print $0}' 默认换行输出环境变量
BEGIN模式制定
head -n5 /etc/passwd | awk 'BEGIN{FS=':'};{print $5}' 打印冒号作为分隔符的第五列 (less more 分页查看)
awk -F: '$3>500{print $0}' /etc/passwd 打印第三列大于500的
程序用户500-999 普通用户1000-65534
awk -F:'{if ($3>500){print $0 }}' /etc/passwd 打印第三列大于500的
awk -F:'!($3>10){print $0}' /etc/passwd 第三列小于等于十的全部打印(取反判断)
格式:awk '(条件表达式)?(A表达式或者值):(B表达式或者值)'
awk -F:'{max=($3>=$4)?$3:$4;{print max,$0}}' /etc/passwd | sed -n '1,6p' 比较passwd文件中以":"为分割的第三个和 第四个字段的大小。
?:运算符是if-else语句的简写,因此此行等效于 if ($3>= $4) {max=$3} else {max=$4}
取比较结果的最大值,赋值给变量max,并且输出max行的所有内容,然后打印其中的1-6行。
awk精确筛选
$n(><==):用于对比数值
$n~"字符串":代表第n个字段包含某个字符串
$n!~"字符串":代表第n个字段不包含某个字符串
$n=="字符串":代表第n个字段为某个字符串
$n!="字符串":代表第n个字段不为某个字符串
$NF:代表最后一个字段
输出第七个字段包含‘bash’所在行的第一个字段和最后一个字段
awk -F: ' $7~ "bash"{print $1,$NF}' /etc/passwd
不包含输出第七个字段包含‘bash’所在行的第一个字段和最后一个字段
awk -F: '$7!~"nologin"{print $1,$NF}' /etc/passwd
第六段包含/home/xny和第七个字段包含bin/bash的行 打印第一和最后字段:
awk -F:'($6=="/home/xny")&&($7=="/bin/bash"){print $1,$NF}' /etc/passwd
RS默认分隔符\n 换行 awk从资料中读取资料时,将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录进行处理。也可以使 用BEGIN模式在操作前进行行分隔符的改变。
以冒号为分隔符的全部内容进行打印,以默认RS\n进行分隔打印(NR序号)
echo $PATH | awk 'BEGIN{RS=":"};{print NR,$0}'
指定输出的分隔符:
OFS:输出内容的列分隔符($n=$n用于激活,否则不生效,n且必须存在)
echo a b c d | awk '{OFS=":";$1=$1;print $0}'
echo a b c d | tr " " ":"
echo a b c d | awk 'BEGIN{OFS=":"};{$1=$1;print $0}' 结果:a:b:c:d
awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30......;print a[1]}'
形成数组遍历
awk 'BEGIN{a[0]=10;a[1]=20;a[2]=20;a[3]=30;for(i in a)print i,a[i]}' 在awk中打印变量不需要加$
awk '{a[$1]++};END{for(i in a){print i,a[i]}}' 文件名
遍历几次由行数决定 ★取小数点几位和取整数 (printf:f调用%.f方法)
result=$(awk 'BEGIN{printf "%.2f",2.32332*2.3213}') 取小数点2位
result=$(awk 'BEGIN{printf "%.F",2.32332*2.3213}') 取整(四舍五入)
简单日志分割
awk '{print $1, $7, $9}' /var/log/messages
提取主机名放入host文件:
awk -F'[ .]+' '{print $2}' 111.txt >host
磁盘可用容量(G)
df | grep -w centos-root | awk '{sum+=$4} END{print "磁盘可用容量:"sum/1024/1024}'
df -h | awk '$NF=="/"{print $4}'
etc下文件的大小和(M)
ls -l /etc/ | awk '/^-/ {sum+=$5} END{print "文件总大小:"sum/1024“M”}