文章目录
- 9.1 什么是awk
- 9.2 awk命令格式
- 9.3 awk执行流程
- 9.4 行与列
- 9.4.1 取行
- 9.4.2 取列
9.1 什么是awk
虽然sed编辑器是非常方便自动修改文本文件的工具,但其也有自身的限制。通常你需要一个用来处理文件中的数据的更高级工具,它能提供一个类编程环境来修改和重新组织文件中的数据。这正是awk能够做到的。
awk程序是Unix中的原始awk程序的GNU版本。 awk程序让流编辑迈上了一个新的台阶,它提供了一种编程语言而不只是编辑器命令。在awk编程语言中,你可以做下面的事情:
- 定义变量来保存数据;
- 使用算术和字符串操作符来处理数据;
- 使用结构化编程概念(比如if-then语句和循环)来为数据处理增加处理逻辑;
- 通过提取数据文件中的数据元素,将其重新排列或格式化,生成格式化报告。
awk程序的报告生成能力通常用来从大文本文件中提取数据元素,并将它们格式化成可读的报告。其中最完美的例子是格式化日志文件。在日志文件中找出错误行会很难, awk程序可以让你从日志文件中过滤出需要的数据元素,然后你可以将其格式化,使得重要的数据更易于阅读。
结构化数据:意思是数据的格式是固定的,例如在数据库中存储人的信息可以通过以下字段来定义
id name age birth gender like …
1 张三 20 5.26 男 看书
2 李四 18 男 电影
3 王五 19 4.5 女
半结构化数据:它可能部分信息是有一定固定结构,而另一部分则没有固定结构。例如日志内容
date ip method
非结构化数据:数据是没有固定结构的,例如图片、电影、音乐这类文件都是非结构化数据
9.2 awk命令格式
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
选项 | 描述 |
---|---|
-F fs | 指定行中划分数据字段的字段分隔符 |
-f progfile | 从指定文件中读取程序 |
-v var=val | 在awk中定义一个变量及其默认值 |
-mf N | 指定要处理的数据文件中最大的字段数 |
-mr N | 指定数据文件中最大数据的行数 |
官方示例:
Examples:
awk '{ sum += $1 }; END { print sum }' file
awk -F: '{ print $1 }' /etc/passwd
9.3 awk执行流程
例如执行如下的命令:
awk -F , 'BEGIN{print "name"}{print $2}END{print "end of file"}' openlab.txt
所操作的流程:
9.4 行与列
名词 | awk中叫法 | 一些说明 |
---|---|---|
行 | 记录 record | 每一行默认通过回车分割的 |
列 | 字段,域 field | 每一列默认通过空格分割的 |
9.4.1 取行
awk | 说明 |
---|---|
NR==1 | 取出某一行 |
NR>=1&&NR<=5 | 取出1~5号 |
/openlab/ | 过滤 |
/101/,/105/ | 取出 101~105 |
符号 | > >= < <= == != |
使用示例:
[root@openEuler ~]# vim openlab.txt
[root@openEuler ~]# cat openlab.txt
My name is jock.
I teach linux.
101
I like play computer game.
My qq is 24523452
105
openlab is good
# 1. 获取第一行
[root@openEuler ~]# awk 'NR==1' openlab.txt
My name is jock.
# 2. 范围获取,获取1~5行
[root@openEuler ~]# awk 'NR>=1 && NR<=5' openlab.txt
My name is jock.
I teach linux.
101
I like play computer game.
My qq is 24523452
# 3. 从文件中过滤 /openlab
[root@openEuler ~]# awk '/openlab/' openlab.txt
openlab is good
9.4.2 取列
awk | 说明 |
---|---|
-F | 指定分割符,指定每一列结束标记(默认是空格,连续的空格,tab键) |
$n | 取出某一列,n是从1开始的整数 |
$0 | 取出所有列,即整行 |
$NF | 最后一列 |
$(NF-1) | 最后第二列 |
-v | 定义分割符变量的值 |
FS | Field Separator 字段分割符,每个字段结束标记,-v FS=: 它等价于 -F: |
OFS | Output Field Separator 输出字段分割符(awk显示每一列时,每一列之间通过什么分割,默认是空格) |
示例:
# 取出ls -l 命令输出结果的第5列
[root@openEuler ~]# ls -l | awk '{print $5}'
916
4096
119072917
125801637
8287769
10675730
7892
102
2413
92584268
0
4958
79
# 取出ls -l 命令输出结果的第5列和最后一列
[root@openEuler ~]# ls -l|awk '{print $5,$9}'
916 anaconda-ks.cfg
4096 data
119072917 grafana-enterprise-10.4.2-1.x86_64.rpm
125801637 grafana-enterprise-10.4.2.linux-amd64.tar.gz
8287769 mysqld_exporter-0.15.1.linux-amd64.tar.gz
10675730 node_exporter-1.8.0.linux-amd64.tar.gz
7892 nohup.out
102 openlab.txt
2413 passwd
92584268 prometheus-2.45.4.linux-amd64.tar.gz
0 sshd_config
4958 sshd_configr
79 test.txt
[root@openEuler ~]# ls -l|awk '{print $5,$(NF)}'
348116
916 anaconda-ks.cfg
4096 data
119072917 grafana-enterprise-10.4.2-1.x86_64.rpm
125801637 grafana-enterprise-10.4.2.linux-amd64.tar.gz
8287769 mysqld_exporter-0.15.1.linux-amd64.tar.gz
10675730 node_exporter-1.8.0.linux-amd64.tar.gz
7892 nohup.out
102 openlab.txt
2413 passwd
92584268 prometheus-2.45.4.linux-amd64.tar.gz
0 sshd_config
4958 sshd_configr
79 test.txt
# 3. 将输出的结果列对齐
[root@openEuler ~]# ls -l|awk '{print $5,$(NF)}'| column -t
348116
916 anaconda-ks.cfg
4096 data
119072917 grafana-enterprise-10.4.2-1.x86_64.rpm
125801637 grafana-enterprise-10.4.2.linux-amd64.tar.gz
8287769 mysqld_exporter-0.15.1.linux-amd64.tar.gz
10675730 node_exporter-1.8.0.linux-amd64.tar.gz
7892 nohup.out
102 openlab.txt
2413 passwd
92584268 prometheus-2.45.4.linux-amd64.tar.gz
0 sshd_config
4958 sshd_configr
79 test.txt
# 4. 使用awk调换/etc/passwd文件的第一列和最后一列的内容
[root@openEuler ~]# awk -F: -v OFS=: '{print $NF,$2,$3,$4,$5,$6,$1}' passwd | head -5
/bin/bash:x:0:0:Super User:/root:root
/usr/sbin/nologin:x:1:1:bin:/bin:bin
/usr/sbin/nologin:x:2:2:daemon:/sbin:daemon
/usr/sbin/nologin:x:3:4:adm:/var/adm:adm
/usr/sbin/nologin:x:4:7:lp:/var/spool/lpd:lp
注意:$(NF) 表示获取最后一列,最后第二列是 $(NF-1)
案例:取出网卡中的 IP 地址。
# 使用 sed 来实现
[root@openEuler ~]# ip a show ens160|sed -n '3p'|sed -r 's/(.*t )(.*)(\/.*$)/\2/g'
192.168.72.131
# 使用awk 来实现
[root@openEuler ~]# ip a show ens160|awk 'NR==3'|awk -F'[ /]+' '{print $3}'192.168.72.131
NR:Number of Record
NF:Number of Field