Linux三剑客之一awk
awk
grep、sed和awk都是读一行处理一行,直至处理完成
定义
格式化文本
格式
awk [参数][分隔符] '{[处理规则]}' [操作对象]
awk [参数][分隔符] '{BEGIN{开始初需要的处理}/定位/{循环}END{结束前需要的处理}}' [操作对象]
参数
-F :指定文本中的分隔符(默认是以空格作为分隔符)
案例:打印系统所有用户的解析器
awk -F: '{print $NF}' /etc/passwd
生命周期(执行的过程)
1.读取一行作为待处理文本
2.把刚刚读取进来的文本进行分解
3.再使用处理规则处理待处理文本
4.处理完,赋值给$0
5.把处理完成之后的所有的数据交给END{}来再次处理
预定义变量
$0 :当前行所有数据
awk -F: '{print $0, "---"}' /etc/passwd # 每行后面加上---
,是默认以空格作为分隔符拼接的意思
$n :第n列
awk -F: '{print $1}' /etc/passwd # 第一列
NF :记录当前行的字段数(就是分隔符分了多少段数)
awk -F: '{print NF}' /etc/passwd # 每行分了多少段
awk -F: '{print $NF}' /etc/passwd # 只显示最后一列
NR :记录行号
awk -F: '{print NR}' /etc/passwd # 给每行递增编号
FS :指定文本中的分隔符(默认空格)(与-F的作用相似 , 但优先级比之优先)
定义在BEGIN{FS="指定原文本内分隔符"}中
awk 'BEGIN{FS=":"}{print $NF, $1}' /etc/passwd # 以“:”读取最后一列和第一列
OFS :指定读取处理出来的文本中使用的分隔符(默认空格)
定义在BEGIN{FS="指定新文本中分隔符"}中
awk -F: 'BEGIN{OFS=" >>> "}{print $NF, $1}' /etc/passwd # 读取最后一列和第一列中间使用>>>拼接在一起
处理规则中执行顺序
awk [参数][分隔符] '{BEGIN{开始初需要的处理}/定位/{循环}END{结束前需要的处理}}' [操作对象]
BEGIN{} :开始前需要的处理
// :定位
{} :循环
END{} :结束前需要的处理
内置函数
awk -F: 'BEGIN{OFS=" | "}{printf "|%+15s|%-15s|\n", $NF,$1}' /etc/passwd
print :打印
printf :格式化打印
%s :字符串
%d :数字
- :左对齐
+ :右对齐
15 :至少占用15字符
定位
1.正则表达式
awk -F: '/root/{print $0}' /etc/passwd # 打印含root所在行的所有内容
awk -F: '/^root/{print $0}' /etc/passwd # 打印以root开头所在行的所有内容
2.比较表达式(文本内部数据比较)
> :大于
< :小于
>= :大于等于
<= :小于等于
~ :表示匹配后面的正则表达式
!~ :表示(取反)后面的正则表达式的结果
案例:
案例1:要求打印属组ID大于属主ID的行
awk -F: '$4 > $3{print $0}' /etc/passwd # 匹配打印出第4列比第3列大的行
案例2:结尾包含bash
awk -F: '$NF ~ /bash/{print $0}' /etc/passwd # 读取最后一列给到后面正则表达式筛选出含bash的行
案例3:结尾不包含bash
awk -F: '$NF !~ /bash/{print $0}' /etc/passwd # 读取最后一列给到后面正则表达式筛选出不含bash的行
3.逻辑表达式
&& :逻辑与
awk -F: '$3 + $4 > 2000 && $3 * $4 > 2000{print $0}' /etc/passwd # 必须同时满足两个条件
|| :逻辑或
awk -F: '$3 + $4 > 2000 || $3 * $4 > 2000{print $0}' /etc/passwd # 只要满足一个条件
! :逻辑非
awk -F: '!($3 + $4 > 2000){print $0}' /etc/passwd # 必须两个条件同时都不满足
4.算术表达式
+ :加
- :减
* :乘
/ :除
% :取余
案例:
案例1:要求属组 + 属主的ID 大于 2000
awk -F: '$3 + $4 > 2000{print $0}' /etc/passwd
案例2:要求属组 * 属主的ID 大于 2000
awk -F: '$3 * $4 > 2000{print $0}' /etc/passwd
案例3:要求打印偶数行
awk -F: 'NR % 2 == 0{print $0}' /etc/passwd
案例4:要求打印奇数行
awk -F: 'NR % 2 == 1{print $0}' /etc/passwd
5.条件表达式(内部数据与指定数据比较)
== :等于(相同)
> :大于
< :小于
>= :大于等于
<= :小于等于
案例:要求打印第三行
awk -F: 'NR == 3{print $0}' /etc/passwd # 指定 行编号为3的打印
6.范围表达式
一个选定条件到另一个选定条件之间的数据
eg:
awk -F: '/^root/,/^ftp/{print $0}' /etc/passwd # 以root开头的行到以ftp开头的行中间的行
流程控制
只存在循环中
if
格式:
if(){}
if(){}else{}
if(匹配条件){成立后的处理}else if(再匹配条件){成立后的处理}else{还不成立的处理}
eg:
awk -F: '{if($3>$4){print "大于"}else{print "小于或等于"}}' /etc/passwd
for
格式:
for(i="初始值";条件判断;游标){}
eg:
awk -F: '{for(i=10;i>0;i--){print $0}}' /etc/passwd
-- :每次减1
while
格式:
while(条件判断){}
eg:
awk -F: '{i=1; while(i<10){print $0, i++}}' /etc/passwd
++ :每次加1
案例:每隔5行,打印一行横线(----------------------------)
awk -F: '{if(NR%5==0){print "----------------"}print $0}' /etc/passwd