CentOS7 自动化运维基础 Awk
hyui 4/1/2020 linuxBash
# Awk
# Awk简介
- Awk是一种编程语言,可以在Linux下对文本和数据进行扫描与处理,数据可以来自标准输入、文件、管道。
# Awk工作流程
- 逐行扫描文件 --> 从第一行到最后一行 --> 寻找匹配特定模式的行 --> 进行用户操作
- Awk的两个特殊模式:
- BEGIN模式:awk将在读取任何输入行之前执行BEGIN中的操作。
- END模式:awk将在正式退出之前执行END中的操作。
# Awk基本语法格式
gawk [选项] -f program-file [--] file ...
POSIX options: GNU long options: (standard)
-f progfile --file=progfile
-F fs --field-separator=fs
-v var=val --assign=var=val
Short options: GNU long options: (extensions)
-b --characters-as-bytes
-c --traditional
-C --copyright
-d[file] --dump-variables[=file]
-e 'program-text' --source='program-text'
-E file --exec=file
-g --gen-pot
-h --help
-L [fatal] --lint[=fatal]
-n --non-decimal-data
-N --use-lc-numeric
-O --optimize
-p[file] --profile[=file]
-P --posix
-r --re-interval
-S --sandbox
-t --lint-old
-V --version
# Awk操作指令
# 记录与字段
- Awk一次从文件中读取一条记录,并将记录存储在字段变量$0中。记录为分割为字段并存储在$1,$2,...,$NF中(默认使用空格或制表符为分隔符)。
#读取输入行,并输出第一个字段、第二个字段、第三个字段
[root@Hyui-VM ~]# echo hello the world | awk '{print $1,$2,$3}'
hello the world
#读取输入行,直接输出该行
[root@Hyui-VM ~]# echo hello the world | awk '{print $0}'
hello the world
#输出该行的字段个数
[root@Hyui-VM ~]# echo hello the world | awk '{print NF}'
3
#输出该行最后一个字段
[root@Hyui-VM ~]# echo hello the world | awk '{print $NF}'
world
# 字段分隔符
- Awk默认使用空格和制表符作为分隔符,使用-F和FS可以改变分隔符。
[root@Hyui-VM ~]# awk -F: '{print $1}' /etc/passwd
[root@Hyui-VM ~]# awk 'BEGIN {FS=":"} {print $1}' /etc/passwd
- 以上两种方法都是将":"设定为分隔符,以":"为分隔符打印passwd文件的第一个字段。
- 如何指定多个字段分隔符?
[root@Hyui-VM ~]# echo 'hello the:world,!' | awk 'BEGIN {FS="[:,]"} {print $1,$2,$3,$4}'
hello the world !
# 内置变量
# 变量列表
变量名称 | 描 述 |
---|---|
ARGC | 命令行参数个数 |
FILENAME | 当前输入文档名称 |
FNR | 当前输入文档当前记录编号 |
NR | 输入流的当前记录编号 |
NF | 当前记录的字段个数 |
FS | 字段分隔符 |
OFS | 输出字段分隔符,默认为空格 |
ORS | 输出记录分隔符,默认换行符\n |
RS | 输入记录分隔符,默认为\n |
# 示例1
[root@Hyui-VM ~]# cat neko.html
<html>
<title>Neko Site</title>
<body>
h1Cute Nekoh1
h2Kawaii Nekoh2
h3Yasashi Nekoh3
</body>
</html>
[root@Hyui-VM ~]# cat network
DEVICE=eno16777736
onboot=yes
BOOTPROTO=static
ipaddr=192.168.0.1
nEtMaSt=255.255.255.0
GaTeWaY=192.168.0.254
- 输出当前文档的当前编号,第一个文件有8行,第二个文件有6行。
[root@Hyui-VM ~]# awk '{print FNR}' neko.html network
1
2
3
4
5
6
7
8
1
2
3
4
5
6
- 将两个文档作为一个整体输入流,通过NR输入当前编号。
[root@Hyui-VM ~]# awk '{print NR}' neko.html network
1
2
3
4
5
6
7
8
9
10
11
12
13
14
- 文档每行的字段数量。
[root@Hyui-VM ~]# awk '{print NF}' neko.html
1
2
1
2
2
2
1
1
# 示例2
- 通过OFS将输出分隔符设置为"-"。
[root@Hyui-VM ~]# cat test.txt
This is a test file.
Welcome to CentOS Linux 7.
root@Hyui-VM ~]# awk 'BEGIN {OFS="-"} {print $1,$2,$3}' test.txt
This-is-a
Welcome-to-CentOS
# 表达式与操作符
- 操作符示例
[root@Hyui-VM ~]# echo "test" | awk 'x=2 {print x+3}'
5
[root@Hyui-VM ~]# echo "test" | awk 'x=2,y=3 {print x+3, y*3}'
5 9
#输出sshd_config所有空白行
[root@Hyui-VM ~]# awk '/^$/ {print x+=1}' /etc/ssh/sshd_config
1
2
3
4
5
......[省略]
#输出sshd_config总空白行个数
[root@Hyui-VM ~]# awk '/^$/ {x+=1} END {print x}' /etc/ssh/sshd_config
27
#列出passwd的id大于500的用户名
[root@Hyui-VM ~]# awk -F: '$3>500 {print $1}' /etc/passwd
polkitd
chrony
# Awk高级应用
# If条件判断
- 格式:
if (表达式)
动作1
else
动作2
if (表达式) 动作1; else 动作2
- 判断vda1可用存储是否不足2G
[root@Hyui-VM ~]# df | grep vda1 | awk '{if($4<2000000) Print "Insufficient storage"; else print "OK"}'
OK
# While循环
- 格式1:
while(条件)
动作
- 示例:
[root@Hyui-VM ~]# awk 'i=1 {} BEGIN {while(i<=5){++i; print i}}' neko.html
1
2
3
4
5
6
- 格式2:
do
动作
while(条件)
- 示例:
[root@Hyui-VM ~]# awk 'BEGIN { do {++x; print x} while (x<=5)}' neko.html
1
2
3
4
5
6
# For循环
for (变量;条件;计数器)
动作
- 示例:
[root@Hyui-VM ~]# awk 'BEGIN {for (i=1;i<=5;i++) print i}' neko.html
1
2
3
4
5
# 函数
# rand()函数
- 作用:产生0~1之间的浮点类型随机数。
- 示例:
[root@Hyui-VM ~]# awk 'BEGIN{print rand(); srand(); print srand()}' test.txt
0.237788
1585732218
- 使用srand()使每次产生的随机数不同
# gsub(x,y,z)函数
- 作用:在字串z中使用字串y替换与正则表达式x相匹配的所有字串,z默认为$0。
# sub(x,y,z)函数
- 作用:在字串z中使用字串y替换与正则表达式x相匹配的di'yi'g字串,z默认为$0。
[root@Hyui-VM ~]# awk -F: 'gsub(/root/,"centos",$0) {print $0}' /etc/passwd
centos:x:0:0:centos:/centos:/bin/bash
operator:x:11:0:operator:/centos:/sbin/nologin
[root@Hyui-VM ~]# awk -F: 'sub(/root/,"centos",$0) {print $0}' /etc/passwd
centos:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/centos:/sbin/nologin
# length(z)函数
- 作用:计算并返回字串长度。
[root@Hyui-VM ~]# awk '{print length()}' test.txt
20
26
# getline函数
- 作用:从输入中读取下一行内容。
[root@Hyui-VM ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 424K 1.9G 1% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/vda1 40G 2.1G 36G 6% /
tmpfs 379M 0 379M 0% /run/user/0
[root@Hyui-VM ~]# df -h | awk '{if(NF==1) {getline; print $3}; if(NF==6) print $4}'
1.9G
1.9G
1.9G
1.9G
36G
379M