awk基本用法及脚本
1、awk命令及基本用法
- awk不仅仅是一个命令,还是一种编程语言,用于在linux下对文本和数据进行处理,主要用于计算或统计日志等
- 而且他支持用户自定义函数和动态正则表达式等先进功能,是Linux下的一个强大编程工具
awk基本用法
在默认情况下是以空格为分隔符,且多个空格会自动认为一个
[root@localhost ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 7.9G 0 rom
nvme0n1 259:0 0 20G 0 disk
├─nvme0n1p1 259:1 0 1G 0 part /boot
└─nvme0n1p2 259:2 0 19G 0 part
├─rhel-root 253:0 0 17G 0 lvm /
└─rhel-swap 253:1 0 2G 0 lvm [SWAP]
[root@localhost ~]# lsblk | awk '{print $2 }' //打印第二列内容
MAJ:MIN
11:0
259:0
259:1
259:2
253:0
253:1
1.1 工作原理
逐行读取文本,默认以空格或tab键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。
sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个“字段”然后再进行处理。 awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示。在使用awk命令的过程中,可以使用逻辑操作符“&&”表示“与”、“||”表示“或”、“!”表示“非”;还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加、减、乘、除、取余和乘方。
1.2 格式及演示
awk [选项] ‘[模式动作]’ files
参数选项:
参数选项 | 说明 |
---|---|
-F | 指定分隔符 |
-f | 指定脚本文件名 |
-v | var=value 赋值一个用户定义变量,将外部变量传递给awk |
常用变量:
动作 | 说明 |
---|---|
$1 | 打印第一列 |
$0 | 打印整行 |
NF | 当前处理的行的字段个数 |
$NF | 打印最后一列 |
$(NF-n) | 打印倒数第n列 |
NR | 当前处理的行的行号(序数) |
演示:
1、以:为分割符,打印第一列和最后一列,并显示这一行中有多少列即多少个被:分开的字段
[root@localhost ~]# awk -F ":" '{print $1,$NF,NF}' /etc/passwd
root /bin/bash 7
bin /sbin/nologin 7
daemon /sbin/nologin 7
adm /sbin/nologin 7
2、用awk提取出test文件中的第二到第三行
[root@localhost ~]# awk 'NR==2,NR==3' test
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
3、使用awk过滤包含某些内容的行。和sed类似把需要过滤的内容用斜杠抱起来
[root@localhost ~]# awk '/root/' test
root:x:0:0:root:/root:/bin/bash
4、获取IP地址
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:78:3d:b1 brd ff:ff:ff:ff:ff:ff
inet 192.168.164.133/24 brd 192.168.164.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet6 fe80::1a7e:86eb:1321:32d3/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@localhost ~]# ip a | grep 'inet '| grep -v '127.0.0.1/8' | awk -F'[ / ]+' '{print $3}'
192.168.164.133
//grep -v 取反筛选,以‘/’和空格为分隔符,取第三个就是IP地址。因为inet的前面有很多空格其中一个是分隔符,所以inet是$2
第二种方法:
[root@localhost ~]# ifconfig | sed -n "/inet /p" | grep -v 127.0.0.1 | awk '{print $2}'
192.168.164.133
5、输出文本内容
- \n:转换
- \t:tab键
[root@localhost ~]# echo |awk 'BEGIN{print "name""\t""age""\n""xixi""\t""83""\n""haha""\t""20""\n""jjyy""\t""18"}'
name age
xixi 83
haha 20
jjyy 18
2、awk高级用法
2.1 FS,OFS 输入输出分隔符
FS:出入分隔符
OFS:输出分隔符
默认都是以空格为分隔符 ,就是空格
[root@localhost ~]# cat test
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost ~]# awk 'BEGIN{FS=":"}{print $1,$7}' test
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
[root@localhost ~]# awk 'BEGIN{FS=":";OFS="-"}{print $1,$7}' test
root-/bin/bash
bin-/sbin/nologin
daemon-/sbin/nologin
adm-/sbin/nologin
lp-/sbin/nologin
//1和7之间的,(空格符)时为了引用OFS,默认的FS和OFS值都为空格。如果不加,(空格符)输出的内容时没有-的
2.2 扩展正则表达式匹配内容
根据扩展正则表达式匹配内容
[root@localhost ~]# awk '/1?(- )?\(?[0-9]+\)?( -)?[0-9]+-[0-9]+/' test02
707-724-0000
(707) 724-0000
(707)724-0000
1-707-724-0000
//“?”匹配前面字符1出现1次或者0次;“[0-9]+”匹配指定范围内的任意单个字符,+并且出现至少一次
转义序列
序列 | 介绍 |
---|---|
\t | tab键 |
\n | 换行键 |
2.3 算数运算
操作符 | 描述 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取模 |
^ | 取幂 |
在awk中如果一个变量没有定义值时默认为0
//因x没有定义所以x值为0,0+1=1
[root@localhost ~]# awk 'BEGIN{y=x+1;print y}'
1
[root@localhost ~]# awk 'BEGIN{y=2;print y+2}'
4
匹配文件中root出现在了几行里面
[root@localhost ~]# awk '/root/{print x += 1}' test
1
赋值操作符
操作符 | 描述 |
---|---|
+ + | 变量加1 |
– | 变量减1 |
+= | 将加的结果赋给变量 |
-= | 将减的结果赋给变量 |
*= | 将乘的结果过赋给变量 |
/= | 将除的结果赋给变量 |
%= | 将取模的结果赋给变量 |
^= | 将取幂的结果赋给变量 |
**= | 将取幂的结果赋给变量 |
i++:在返回结果后递增x的值
++i:在返回结果前递增x的值
[root@localhost ~]# awk '/^$'/{print i++}' test
0
1
2
3
4
5
6
[root@localhost ~]# awk '/^$'/{print ++i}' test
1
2
3
4
5
6
7
2.4 商品脚本
使用awk编写一个商品结算系统
[root@localhost ~]# cat drinks
美年达 3
格瓦斯4
红牛 6
可口可乐 3
//添加行号
[root@localhost ~]# awk '{print NR".",$0}' drinks
1. 美年达 3
2. 格瓦斯4
3. 红牛 6
4. 可口可乐 3
[root@localhost ~]# cat test.sh
#!/bin/bash
echo "饮料清单:"
awk '{print NR".",$1,$2"元"}' drinks
read -p "请输入要买的商品编号: " choice //定义一个编号变量
read -p"请你入够买的数量:" num //定义购买数量变量(脚本变量)
awk -vcount=$num -vline=$choice 'NR==line{print "您一共买了"count"瓶"$1",共消费"$2*count"元。"}' drinks //在awk里定义一个变量line、count,把输入的编号传入到line中,把购买的瓶数输入到count中
//执行脚本
[root@localhost ~]# bash test.sh
饮料清单:
1. 美年达 3元
2. 格瓦斯4元
3. 红牛 6元
4. 可口可乐 3元
请输入要买的商品编号: 2
请你入要买的数量:3
您一共买了3瓶格瓦斯,共消费12元。