shell脚本编程三剑客——之 AWK

AWK攻击阐述

在 Linux/UNIX 系统中,awk 是一个功能强大的编辑工具,逐行读取输入文本,并根据指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,可以在无交互的情况下实现相当复杂的文本操作,被广泛应用于 Shell 脚本,完成各种自动化配置任务。

◆awk 常见用法

●前面提到 sed 命令常用于一整行的处理,而 awk 比较倾向于将一行分成多个“字段”然后再进行处理,且默认情况下字段的分隔符为空格或 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。在使用 awk 命令的过程中,可以使用逻辑操作符“&&”表示“与”、“||” 表示“或”、“!”表示“非”;还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加、减、乘、除、取余和乘方。

◆awk 工作原理

●awk 借用 shell 中类似于位置变量的方法, 用$1、$2、$3…顺序地表示行(记录)中的不同字段。另外 awk 用$0 表示整个行(记录)。不同的字段之间是通过指定的字符分隔。awk 默认的分隔符是空格。awk 允许在命令行中用“-F 分隔符”的形式来指定分隔符。

在这里插入图片描述

◆awk 命令格式

 awk 选项 '模式或条件 {编辑指令}' 文件 1 文件 2 …          过滤并输出文件中符合条件的内容
 
 awk   -f   脚本文件 文件 1 文件 2 …	                  从脚本中调用编辑指令,过滤并输出内容
 
  awk 包含几个特殊的内建变量(可直接用)如下所示:



 FS:      指定每行文本的字段分隔符,默认为空格或制表位。

 NF:      当前处理的行的字段个数。

 NR:      当前处理的行的行号(序数)。

 $0:      当前处理的行的整行内容。

 $n:      当前处理行的第 n 个字段(第 n 列)。

 FILENAME:被处理的文件名。
 
 RS:      “行“分割符,awk从文件上读取资料时,将根据RS的定义把资料切割成许多条记录 
           wak一次仅读入一条记录,以进行处理,预设值是” \n “     

全是实操命令,看完秒懂AWK

准备的文件内容

[root@localhost opt]# cat awk.txt 
1  1
2
3
4
5
10
20
30
40
50
#woood # AAA

#woooooood # BBB

#wood CCC DDD

◆按行输出文本

#下面两条相当于cat awk.txt
awk '{print}' awk.txt
awk '{print$0}' awk.txt
awk 'NR==1,NR==3{print}' test.txt	     #输出第 1~3 行内容
awk '(NR>=1)&&(NR<=3){print}' test.txt	 #输出第 1~3 行内容

#输出第 1 行、第 3 行内容
[root@localhost opt]# awk 'NR==1 || NR==3{print}' sed.txt       
1  1
3
#输出所有奇数行的内容
awk '(NR%2)==1{print}' test.txt

#输出所有偶数行的内容	  
awk '(NR%2)==0{print}' test.txt	  
#输出以1开头的行
[root@localhost opt]# awk '/^1/{print}' awk.txt 
1  1
10

#输出以0结尾的行
[root@localhost opt]# awk '/0$/{print}' awk.txt   
10
20
30
40
50
#先执行BEGIN的内容,最后执行END内容,x=0为变量,两个\为转义字符,
#匹配以/bin/bash结尾的行,每匹配上一次 X+1 最后打印X的值
[root@localhost opt]# awk 'BEGIN {x=0}; /\/bin\/bash$/{x++};END{print x}' /etc/passwd
2

#等同于grep -c
[root@localhost opt]# grep -c "/bin/bash" /etc/passwd
2
#显示有几条文本段落是以空行为分隔的
[root@localhost opt]# awk 'BEGIN{RS=""};END{print NR}' awk.txt  
3

◆按字段输出文本

#输出每行中(以空格或制表符分隔的)第三个字段
[root@localhost opt]# awk '{print$2}' awk.txt

#输出每行中(以空格或制表符分隔) 第1 第3 个字段
[root@localhost opt]# awk '{print$1,$3} awk.txt
#以冒号为分隔符,输出每行中第一个,第三个字段
[root@localhost opt]# awk -F ':' '{print$1,$3}' /etc/passwd
#以冒号为分隔符,先判断出$3<5的行后,才输出$1  $3
[root@localhost opt]# awk -F ':' '$3<5{print$1,$3}' /etc/passwd
root 0
bin 1
daemon 2
adm 3
lp 4
#输出第三段的值不小于200的 行 的$3
[root@localhost ~]# awk -F ':' '!($3<200){print$3}' /etc/passwd
999
998
.......
1000
#等同于上面内容,先处理BEGIN的条件后处理其他条件
[root@localhost ~]# awk 'BEGIN {FS=":"};{if($3>=200){print$3}}' /etc/passwd 
999
998
......
1000
#                 () ? : 三元运算符 代替if    
#                 当$3>$4成立,则输出:前的内容赋值给max
#                 当$3>$4不成立,则输出:后的内容赋值给max
#                 逐行进行
[root@localhost ~]# awk -F ":" '{max=($3>$4)?$3:$4;{print max}}' /etc/passwd
0
1
2
......
1000
48
#输出每一行的行号,每处理一条记录 NR的值+1
[root@localhost ~]# awk -F ':' '{print NR,$0}' /etc/passwd
#输出以冒号分隔,第7个地段中包含/bash的行的第一个字段
[root@localhost ~]# awk -F ':' '$7~"/bash"{print$1}' /etc/passwd
root
zzt
#以冒号为分隔符,第一个字段中包含root且有7个字段的行 的 第1个,第2个字段
[root@localhost ~]# awk -F ":" '($1~"root") && (NF==7){print$1,$2}' /etc/passwd   
root x
#以冒号为分隔符,输出第一个字段即没有/bin/bash,也没有$7!="/sbin/nologin的行 的第二个字符
[root@localhost ~]# awk -F ":" '($7!="/bin/bash") && ($7!="/sbin/nologin"){print$2}' /etc/passwd
x
x
x

◆终极武器 -F 一看秒懂无需注释

[root@localhost ~]# echo "http//www.baidu.com" | awk -F "www." '{print$2}'
baidu.com

[root@localhost ~]# echo "http//www.baidu.com" | awk -F "baidu." '{print$2}'    
com

[root@localhost ~]# echo "http//www.baidu.com" | awk -F ".baidu." '{print$1}'
http//www

◆通过管道符号,双引号调用shell命令

#统计以冒号分隔的文本段落数
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"};END{print NR}'
5
#当getline左右无重定向符和或时,getline作用于当前文件,读入当前文件的第一行给其后跟着的变量var或
$0,由于awk在处理getline之前已经读入了一行,所以getline得到的返回结果是隔行的

#当getline左右有重定向符和或时,getline则作用于定向输入文件,由于该文件是刚打开的,并没有被AWK
读过,只是getline读入,那么geiline返回的是该文件的第一行,而不是隔一行
#调用w 命令,并用来统计在线用户数
awk 'BEGIN {while ("w" | getline) n++ ; {print n-2}}'
#调用hostname,并输出当前的主机名
awk 'BEGIN { "hostname" | getline ; print $0}'

组合使用,其他地方你看不到

#将数组内数字按照顺序排序,并去除重复
A=(1 1 2 3 5 4 6 4)

B=$(for i in ${A[*]};do echo -e $i; done | sort -n | sort -u )

[root@localhost ~]# echo ${B[*]}
1 2 3 4 5 6
#先按照大小排序,然后去除重复
[root@localhost ~]# vi zh.txt
11
22
11
33
44
22
55
44

[root@localhost ~]# cat zh.txt | sort -n |uniq 
11
22
33
44
55
#把 : 换成 换行
[root@localhost ~]# echo $PATH | tr -s ":" "\n"
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin
[root@localhost ~]# echo -e "a\n\n\nb"
a


b
[root@localhost ~]# echo -e "a\n\n\nb" | tr -s "\n"
a
b

猜你喜欢

转载自blog.csdn.net/weixin_48190891/article/details/108294137