文本三剑客之进阶awk
文章目录
一、awk简介
awk是一种处理数据、产生格式化报表的语言,功能也是十分强大,awk认为文件中每一行是一条记录,记录与记录的分隔符为换行符,每一列是一个字段,字段与字段分隔符默认是一个空格,或多个空格。
awk的工作方式是读取数据,将每一行数据视为一条记录,每条记录以字段分隔符分成若干字段,然后输出各个字段的值。
# 常用命令选项:
-F fs 指定文件的分隔符 默认为空格
-f file 指定读取程序的文件名
-v var=value 定义awk程序中使用的变量和默认值
# awk程序的优先级:
BEGIN: 在开始处理数据流之前执行 优先级最高 可选项
program: 如何处理数据流 优先级中等 必选项(默认是program)
END: 处理完数据流后执行 优先级最低 可选项
# 内置变量:
$0 表示整行内容
$1 表示一行中 第一个字段
$2 表示一行中 第二个字段(以此类推)
$NF 表示一行中 最后一个字段
$NR 指定行号
$FIELDWIDTHS 自定义列宽
$FS 输入字段分隔符 类似于F
$OFS 输出字段分隔符
$RS 输入记录分隔符
$ORS 输出记录分隔符
二、awk基本用法
# 演示数据内容:
[root@shell awk]# cat test
1 the quick for jump over the lazy cat . dog
2 the quick for jump over the lazy cat . dog
3 the quick for jump over the lazy cat . dog
4 the quick for jump over the lazy cat . dog
5 the quick for jump over the lazy cat . dog
6 the quick for jump over the lazy cat . dog
1、awk对字段(列)的提取
# 1、打印第3个字段值
[root@shell awk]# awk '{print $2}' test
the
the
the
the
the
the
# 2、打印最后一个字段值
[root@shell awk]# awk '{print $NF}' test
dog
dog
dog
dog
dog
dog
//使用-F 选项可指定字段分隔符
# 3、指定字段分割符为:
[root@shell awk]# awk -F: '{print $1}' passwd
//-v 定义变量
# 4、定义name变量值为qinziteng 调用name变量
[root@shell awk]# awk -v name='qinziteng' 'BEGIN{print name}'
qinziteng
//除了使用-v定义变量 还可以使用=定义变量 如下:
# 5、使用变量查看内存使用率
[root@shell awk]# cat /proc/meminfo |head -3 | awk 'NR==1{n=$2} NR==2{m=$2;print (n-m)*100/n "%" }'
29.3505%
[root@shell awk]# head -3 /proc/meminfo |awk 'NR==1{t=$2}NR==2{f=$2;m=t-f}END {print m/t*100,"%"}'
29.3208 %
2、awk对记录(行)的提取
使用NR 指定行号
# 1、使用NR内置变量 值打印出第一行 第一个字段
[root@shell awk]# awk -F: 'NR==1{print $1}' passwd
root
# 2、打印多个字段
[root@shell awk]# awk -F: 'NR==1{print $1 $2 $3}' passwd
rootx0
//尽管在awk变量与变量直接使用空格相隔开了,输出的值也没用空格的,变量与变量可以使用逗号隔开,输出的值就有空格了,如下:
[root@shell awk]# awk -F: 'NR==1{print $1,$2,$3}' passwd
root x 0
//还是上面这个例子 如果我想要 root-x-0 这种方式显示处理 该如何操作呢?
只需要使用双引号 引起来即可 如下:
[root@shell awk]# awk -F: 'NR==1{print $1"-" $2"-"$3}' passwd
那如果想要 user:root pwd:x uid:0 这样输出 呢? 如下:
[root@shell awk]# awk -F: 'NR==1{print "user:"$1,"pwd:"$2,"uid:"$3}' passwd
user:root pwd:x uid:0
3、awk的优先级
BEGIN: 在开始处理数据流之前执行 优先级最高 可选项
program: 如何处理数据流 优先级中等 必选项(默认是program)
END: 处理完数据流后执行 优先级最低 可选项
# 1、BEGIN 使用BEGIN优先级最高 其意思是在处理出数据流之前做什么 不需要指定文件
[root@shell awk]# awk 'BEGIN{print "qinziteng"}'
qinziteng
# 2、program 默认就是program 需要指定文件
[root@shell awk]# awk -F: 'NR==1{print $1}' passwd
root
# 3、END 使用END优先级最低 其意思是在处理完成数据流之后做什么 不需要指定文件
[root@shell awk]# awk -F: 'NR==1{print $1}END{print $2}' passwd
root
x
# 4、三个连接起来一起使用
[root@shell awk]# awk -F: ' BEGIN{print "start"} {print $1}END{print "stop"}' passwd
三、awk高级用法
awk是一门语言,那么就符合语言的特性,除了可以定义变量之外,还可以定义数组、进行运算、流程控制等。
1、定义数组
语法格式:
数组名称[索引]=值
# 2、定义数组
[root@shell awk]# awk 'BEGIN{array[0]=100;array[1]=200;print array[0],array[1]}'
100 200
2、awk运算
1)赋值运算
= 赋值运算
[root@shell awk]# awk 'BEGIN{a=qin;print "qin"}'
qin
2)比较运算
#比较运算,如果比较的是字符串则按asci编码顺序比较。返回值=1则为真,返回值=0则为假
> 大于
>= 大于等于
< 小于
<= 小于等于
== 等于
!= 不等于
# a等于b
[root@shell awk]# awk 'BEGIN{print "a" == "b"}'
0
[root@shell awk]# awk 'BEGIN{print "a" != "b"}'
1
[root@shell awk]# seq 1 10 >num
#打印出$1大于5
[root@shell awk]# awk '$1>5{print $0}' num
6
7
8
9
10
#打印出$1小于5
[root@shell awk]# awk '$1<5{print $0}' num
1
2
3
4
3)数学运算
+ 加
- 减
* 乘
/ 除
% 求余
** 开方
++ 加1
-- 减1
# 除
[root@shell awk]# awk 'BEGIN{print 100/3 }'
33.3333
# 100的3次方
[root@shell awk]# awk 'BEGIN{print 100**3 }'
1000000
# ++ 和 --
[root@shell awk]# awk 'BEGIN{count=1;count++;print count}'
2
[root@shell awk]# awk 'BEGIN{count=1;count--;print count}'
0
4)逻辑运算
&& 逻辑与 真真为真 真假为假 假假为假
|| 逻辑或 真真为真 真假为真 假假为假
[root@shell awk]# awk 'BEGIN{print 100>=2 && 100>=101 }'
0
[root@shell awk]# awk 'BEGIN{print 100>=2 || 100>=101 }'
1
5)匹配运算
精确匹配:
==
!=
模糊匹配:
~
!~
精确匹配:
# 匹配root
[root@shell awk]# awk -F: '$1=="root"{print $0}' passwd
root:x:0:0:root:/root:/bin/bash
# 精确不匹配 取反
[root@shell awk]# awk -F: '$1!="root"{print $0}' passwd
模糊匹配:
# 模糊匹配
[root@shell awk]# awk -F: '$1 ~ "r"{print $0}' passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
# 模糊不匹配 取反
[root@shell awk]# awk -F: '$1 !~ "r"{print $0}' passwd
3、awk内置变量
$FIELDWIDTHS 自定义列宽
$FS 输入字段分隔符 类似于F
$OFS 输出字段分隔符
$RS 输入记录分隔符 默认是回车
$ORS 输出记录分隔符
# 自定义列宽 要求第一个$1 三个字符 $2 二个字符 $NF 5个字符
[root@shell awk]# awk -F: 'BEGIN{FIELDWIDTHS="3 2 5"}NR==1{print $1,$2,$NF}' passwd
roo t: x:0:0
# 指定输入分隔符
[root@shell awk]# awk 'BEGIN{FS=":"}$1=="root"{print $1,$3,$5}' passwd
root 0 root
# 指定输出分隔符
[root@shell awk]# awk 'BEGIN{FS=":";OFS="-"}$1=="root"{print $1,$3,$5}' passwd
root-0-root
# 指定记录输入分隔符为空
[root@shell awk]# awk 'BEGIN{RS=""}{print $1,$2,$3}' num
1 2 3
# 指定记录输出分隔符为###(默认是回车,这里定义为### 所以就没有了回车了)
[root@shell awk]# awk 'BEGIN{RS="";ORS="###"}{print $1,$2,$3}' num
1 2 3###[root@shell awk]#
四、awk流程控制
1、if语句
[root@shell awk]# cat num
1
2
3
4
5
6
7
8
9
10
1)单if
# 打印出$1大于5的数字
[root@shell awk]# awk '{if($1>5)print $0}' num
6
7
8
9
10
2)if…else
[root@shell awk]# awk '{
if ($1<5)
print $1*2
else
print $1/2
}' num
2
4
6
8
2.5
3
3.5
4
4.5
5
#写成一行的格式 注意eles前有个分号";"
[root@shell awk]# awk '{if ($1>5)print $1+2;else print $1-2 }' num
-1
0
1
2
3
8
9
10
11
12
2、for循环
[root@shell awk]# cat num2
60 50 100
150 30 10
70 100 40
# 列的累加
[root@shell awk]# awk -v 'sum=0' '{sum+=$1}END{print sum}' num
55
# 行的累加
[root@shell awk]# awk '{sum=0;for (i=1;i<4;i++){sum+=$i}print sum}' num2
210
190
210
五、awk小技巧
# 打印文本行数
[root@shell awk]# awk 'END{print NR}' passwd
25
# 打印最后一行内容
[root@shell awk]# awk 'END{print $0}' passwd
nginx:x:998:1002::/home/nginx:/sbin/nologin
# 打印文本有多少列
[root@shell awk]# awk -F: 'END{print NF}' passwd
7