awk基本用法及脚本

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元。

上一篇:在 Linux 中如何禁止用户登录


下一篇:Synchronized 关键字使用、底层原理、JDK1.6 之后的底层优化以及 和ReenTrantLock 的对比