一、awk介绍
1、awk工作原理
逐行读取文本,默认以空格或tab键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。
sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个“字段”然后再进行处理。awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示。在使用awk命令的过程中,可以使用逻辑操作符“&&”表示“与”、“||”表示“或”、“!”表示“非”;还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加、减、乘、除、取余和乘方。
2、命令格式
awk 选项 '模式或条件 {操作}' 文件 1 文件 2 …
awk -f 脚本文件 文件 1 文件 2 …
3、awk常见的内建变量
FS:列分割符。指定每行文本的字段分隔符,默认为空格或制表位。与"-F"作用相同
NF:当前处理的行的字段个数。
NR:当前处理的行的行号(序数)。
$0:当前处理的行的整行内容。
$n:当前处理行的第n个字段(第n列)。
FILENAME:被处理的文件名。
RS:行分隔符。awk从文件上读取资料时,将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录,以进行处理。预设值是'\n'
二、 用法演练
用法一:按行输出文本
1、输出文本所有内容
[root@localhost ~]# awk '{print}' /etc/passwd
或者
[root@localhost ~]# awk '{print $0}' /etc/passwd #$0表示当前处理的行的整行内容。
2、输出具体行内容
#输出/etc/passwd中第一行的内容
[root@localhost ~]# awk 'NR==1{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
显示1到3行的内容
#输出/etc/passwd中1到3行的内容
[root@localhost ~]# awk 'NR==1,NR==3{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
或者
[root@localhost ~]# awk '(NR>=1)&&(NR<=3){print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
显示第一行和第三行的内容
#显示第一行和第三行的内容
[root@localhost ~]# awk '(NR==1)||(NR==3){print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
输出奇数行和偶数行
[root@localhost ~]# cat test.txt
one
two
three
four
five
six
seven
eight
nigh
ten
#输出奇数行
[root@localhost ~]# cat test.txt | awk '(NR%2)==1 {print $0}'
one
three
five
seven
nigh
#输出偶数行
[root@localhost ~]# cat test.txt | awk '(NR%2)==0 {print $0}'
two
four
six
eight
ten
根据条件查找行内容
#查找包含root的行内容
[root@localhost ~]# awk '/root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
#查找以root开头的行内容
[root@localhost ~]# awk '/^root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
#查找以/bin/bash结尾的行内容
[root@localhost ~]# awk '/\/bin\/bash$/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
test:x:1000:1000:test:/home/test:/bin/bash
BEGIN与END模式的使用
格式:awk 'BEGIN{...};{...};END{...}' 文件
BEGIN模式表示,在处理指定的文本之前,需要先执行BEGIN模式中指定的动作;awk再处理指定的文本,之后再执行END模式中指定的动作,END{}语句块中,往往会放入打印结果等语句。
#打印出/etc/passwd中以/bin/bash结尾的行数
[root@localhost ~]# awk 'BEGIN {x=0};/\/bin\/bash$/{x++};END{print x}' /etc/passwd
2
[root@localhost ~]# grep -c "bash$" /etc/passwd
2
[root@localhost ~]# awk 'BEGIN {x=0}; /bash$/{x++; print x,$0}; END{print x}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
2 test:x:1000:1000:test:/home/test:/bin/bash
2
#匹配以/bash结尾的行,然后执行x++,并打印x和行内容
用法二:按字段输出文本
1、直接输出字段
输出每行以“:”为分隔符的第三个字段
[root@localhost ~]# awk -F ":" '{print $3}' /etc/passwd
#输出以“:”为分隔符的第一个字段和最后一个字段($NF表示最后一个字段)
[root@localhost ~]# awk -F ":" '{print $1,$NF}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
mail /sbin/nologin
operator /sbin/nologin
games /sbin/nologin
ftp /sbin/nologin
..................
2、条件输出字段
#输出以s开头的行内容,并以:为分隔符的第一个和最后一个字段的内容
[root@localhost ~]# awk -F ":" '/^s/{print $1,$NF}' /etc/passwd
sync /bin/sync
shutdown /sbin/shutdown
systemd-network /sbin/nologin
saned /sbin/nologin
saslauth /sbin/nologin
sssd /sbin/nologin
setroubleshoot /sbin/nologin
sshd /sbin/nologin
#找出以:为分隔符的第三个字段的值小于等于5的行,并输出第1、3以及最后一个字段的内容
[root@localhost ~]# awk -F ":" '($3<=5){print $1,$3,$NF}' /etc/passwd
root 0 /bin/bash
bin 1 /sbin/nologin
daemon 2 /sbin/nologin
adm 3 /sbin/nologin
lp 4 /sbin/nologin
sync 5 /bin/sync
#显示行号,且当第三个字段的值小于等于5时,输出整行内容
[root@localhost ~]# awk -F ":" '($3<=5){print NR} ($3<=5){print $0}' /etc/passwd
1
root:x:0:0:root:/root:/bin/bash
2
bin:x:1:1:bin:/bin:/sbin/nologin
3
daemon:x:2:2:daemon:/sbin:/sbin/nologin
4
adm:x:3:4:adm:/var/adm:/sbin/nologin
5
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6
sync:x:5:0:sync:/sbin:/bin/sync
#与上面相同,值得注意的是,如果两个条件一样时,可以写在同一个大括号中用“;”间隔
[root@localhost ~]# awk -F ":" '($3<=5){print NR; print $0}' /etc/passwd
1
root:x:0:0:root:/root:/bin/bash
2
bin:x:1:1:bin:/bin:/sbin/nologin
3
daemon:x:2:2:daemon:/sbin:/sbin/nologin
4
adm:x:3:4:adm:/var/adm:/sbin/nologin
5
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6
sync:x:5:0:sync:/sbin:/bin/sync
3、加上条件语句输出
格式:awk '{控制语句条件 {操作}}' 文件
if的条件则执行操作:awk 'if(条件表达式) {操作}' 文件
#需要加上大括号指定控制语句操作
[root@localhost ~]# awk -F ":" '{if($3<=5){print $0}}' /etc/passwd
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
sync:x:5:0:sync:/sbin:/bin/sync
结合三元运算符输出
awk '变量=条件表达式?值1:值2; {操作}' 文件 #行内容是否条件表达式,如果条件成立则变量取值1,条件不成立则变量取值2
[root@localhost ~]# awk -F ":" '{max=($3>=$4)?$3:$4;{print max}}' /etc/passwd
($3>$4)?$3:$4;三元运算符,如果第3个字段的值大于等于第4个字段的值,则把第3个字段的值赋给max,否则第4个字段的值赋给max。
字段中包含某一字符串的输出
#输出第7个字段中包含login的行,并输出其行号
[root@localhost ~]# awk -F ":" '$7~"login" {print NR,$0}' /etc/passwd
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 operator:x:11:0:operator:/root:/sbin/nologin
11 games:x:12:100:games:/usr/games:/sbin/nologin
4、通过管道与双引号调用shell命令
使用while循环对每行内容执行操作:
awk 'BEGIN{执行循环前的操作; while("命令" | getline) 每次循环的操作; 执行循环完后的操作}'
[root@localhost ~]# awk 'BEGIN {N=0; while("cat /etc/passwd" | getline)n++; print n}'
45
输出所有的目录
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}; {print $0}'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin
三、实例应用
统计ssh登录失败的用户及其登录失败(日志:/var/log/secure中有记录)的次数(通常我们会认为失败三次,存在着暴力破解登录的可能,意味该主机存在隐患)解决方案:将其筛选出来就把IP加入到黑名单中 /etc/hosts.deny。
[root@localhost awk]# awk '/Failed password/{a[$11]++};END{for(i in a){print i,a[i]}}' /var/log/secure
调用w命令,并用来统计在线用户数
awk 'BEGIN {n=0 ; while ("w" | getline) n++ ; {print n-2}}'
查看当前CPU空闲率
top -b -n 1 | grep Cpu | awk -F ',' '{print $4}' | awk '{print $1}'
显示上次系统重启时间
date -d "$(awk -F "." '{print $1}' /proc/uptime) second ago" +"%F %H:%M:%S"
等同于uptime;second ago为显示多少秒前的时间,+"%F %H:%M:%S"等同于+"%Y-%m-%d %H:%M:%S"的时间格式
总结:
awk -F '字段分隔符' 'NR==n {print $0}' #输出 第n行的 整行内容
awk -F '字段分隔符' 'NR==n {print $1}' #输出 第n行的 第一个字段的内容
awk -F '字段分隔符' 'NR==n {print $1,$NF}' #输出 第n行的 第一个字段和最后一个字段的内容
awk -F '字段分隔符' 'NR==n,NR==M {print $1}' #输出 第n行到第m行的 第一个字段的内容
awk -F '字段分隔符' 'NR>=n&&NR<=M {print $1}'
awk -F '字段分隔符' 'NR==n||NR==M {print $1}' #输出 第n行和第m行的 第一个字段的内容
awk -F '字段分隔符' '/字符串/ {print $1}' #输出 包含指定字符串的行的 第一个字段的内容
awk -F '字段分隔符' '/正则表达式/ {print $1}' #输出 匹配正则表达式的行的 第一个字段的内容
awk -F '字段分隔符' '$1>=n {print $0}' #输出 第一个字段的数值大于等于n的 整行内容
== != >= > <= <
awk -F '字段分隔符' '$1~"字符串" {print $0}' #输出 第一个字段包含指定字符串的 整行内容
~(包含) !~(不包含) ==(等于) !=(不等于)
标签:bin,sbin,awk,Linux,print,root,localhost
From: https://blog.csdn.net/qq_54188720/article/details/139561406