个人博客
https://blog.csdn.net/cPen_web
awk 是什么?
答:awk是linux里的一个文本处理的命令(工具) --> 程序 --> c语言
unix --> awk
为什么要使用awk?
答:截取内容
字段:field --> 列 column
name age sex grade
cali 18 M 70
rose 19 F 90
#注:CSV文件 以,作为分割的文件
$0 存储的是整行数据
每个数据存入$1-$7中
awk 默认的分隔符是空白(空格、tab)
输入分隔符 -F
输出分隔符 ,
[root@cPen_A lianxi]# cat /etc/passwd|awk -F":" '{print $1$3$7}'
root0/bin/bash
[root@cPen_A lianxi]# cat /etc/passwd|awk -F":" '{print $1,$3,$7}'
root 0 /bin/bash
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: 'BEGIN{print "######start######"} /bash$/{print $1,$7}END{print "######end######"}'
######start######
root /bin/bash
sanchuang /bin/bash
……
chen223344 /bin/bash
######end######
#注:/bash$ 以bash结尾的行
示例:统计有多少行
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: 'BEGIN{i=0} {i++} END{print i}'
65
#注:不需要用$,因为引用的不是变量
#注:多条命令使用,在{花括号}里放;号
#注:~波浪符号 模糊匹配 ~/feng/; || 或;&& 且
awk内置变量
NR 代表行号 number of record --> record 记录 --> 行
NF 代表一行的字段数量 number of field
$NF 表示最后一个字段;$(NF-1)倒数第一个字段
[root@cPen_A lianxi]# cat /etc/passwd |awk -F: 'BEGIN{num=0;print "开始统计/etc/passwd文件"} $1 ~ /feng/ || $3 > 1005 {print NR,NF,$1,length($1),$(NF-1),$NF,$3;num++}END{print "统计结束",num}'
开始统计/etc/passwd文件
24 7 chenpeng1 9 /home/chenpeng1 /bin/bash 1100
25 7 chenpeng2 9 /home/chenpeng2 /bin/bash 1200
……
65 7 nfsnobody 9 /var/lib/nfs /sbin/nologin 65534
统计结束 37
示例:AWK过滤功能
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '/xiexy/'
[root@cPen_A lianxi]# cat /etc/passwd|egrep "xiexy"
示例:AWK截取功能
[root@cPen_A lianxi]# who |awk '{print $2}'
tty1
pts/2
[root@cPen_A lianxi]# who |awk '{print $2,$4}'
tty1 11:23
pts/2 09:38
示例:自定义的字符串和字段拼接
[root@cPen_A lianxi]# who |awk '{print "time:"$4,"name:"$2}'
time:11:23 name:tty1
time:09:38 name:pts/2
示例:/^[^abcdefg]/ 不是以abcdefg开头的行
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '/^[^abcdefg]/{print $1,$7}'
示例:/^[^A-z]/ 不是A-z字母开头的行
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '/^[^A-z]/{print $1,$7}'
示例:指定2个分割符
[root@cPen_A lianxi]# cat /etc/passwd|tail -1|awk -F[:/] '{print $8}'
lib
awk命令的操作符
比较操作符:匹配符号 ~ !~
示例
[root@cPen_A lianxi]# who
root tty1 2020-12-23 11:23
root pts/2 2021-01-08 09:38 (192.168.0.119)
[root@cPen_A lianxi]# who|awk '$2 ~ /pts/{print $0}'
root pts/2 2021-01-08 09:38 (192.168.0.119)
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '$1 ~/deng/ && $3>1058 && $NF ~/bash$/'
文本数据表达式:
== 精确匹配
~ 模糊匹配
[root@cPen_A lianxi]# awk -F: '$3 ~ /\<...\>/ {print $1,$3}' /etc/passwd
systemd-network 192
polkitd 999
chrony 998
nginx 997
[root@cPen_A lianxi]# awk -F: '$3 ~ /\<.{3}\>/ {print $1,$3}' /etc/passwd
systemd-network 192
polkitd 999
chrony 998
nginx 997
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '$1 ~ /deng/ {print $1}'
awk内置变量和函数
NF 每行$0的字段数
NR 当前处理的行号
FS 当前的输入分隔符,默认是空白字符(空格和tab) field separator
OFS 当前的输出分隔符,默认是空格字符(空格) output field separator
示例
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '{print NR,$0}'
1 root:x:0:0:root:/root:/bin/bash #注:NR行号
2 bin:x:1:1:bin:/bin:/sbin/nologin
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '{print NR,$0,NF}'
1 root:x:0:0:root:/root:/bin/bash 7
2 bin:x:1:1:bin:/bin:/sbin/nologin 7
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '{print NR,$0,$NF}'
1 root:x:0:0:root:/root:/bin/bash /bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin /sbin/nologin
[root@cPen_A lianxi]# cat /etc/passwd|awk 'FS=":";OFS="#"{print NR,$0,$NF}'
root:x:0:0:root:/root:/bin/bash
1#root:x:0:0:root:/root:/bin/bash#root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
2#bin:x:1:1:bin:/bin:/sbin/nologin#/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
#推荐使用-F指定输入分隔符
使用NF变量显示passwd文件倒数第二列的内容
[root@cPen_A ~]# cat /etc/passwd|awk -F: '{print $(NF-1)}'
显示passwd文件中第5到第10行的用户名
[root@cPen_A ~]# cat /etc/passwd|awk -F: 'NR >= 5 && NR <= 10 {print $1}'
[root@cPen_A ~]# cat /etc/passwd|awk -F: 'NR >= 5 && NR <= 10 {print NR,$1}'
显示passwd文件中第7列不是bash的用户名
[root@cPen_A ~]# cat /etc/passwd|awk -F: '$7 ~ /bash/ {print NR,$1}'
显示passwd文件中行号是5结尾的行号和行
[root@cPen_A ~]# cat /etc/passwd|awk -F: 'NR ~ /5$/ {print NR,$1}'
用ip add只显示ip(不能使用tr或者cut命令)
[root@cPen_A ~]# ip add|awk '$NF ~ /ens33/ {print $0}'
inet 192.168.0.118/24 brd 192.168.0.255 scope global noprefixroute dynamic ens33
[root@cPen_A ~]# ip add|awk '$NF ~ /ens33/ {print $2}'
192.168.0.118/24
[root@cPen_A ~]# ip add|awk '$NF ~ /ens33/ {print $2}'|awk -F/ '{print $1}'
192.168.0.118
[root@localhost lianxi]# yum install net-tools -y
先使用ifconfig,使用awk显示eth0的入站流量和出站流量(字节)
[root@cPen_A ~]# ifconfig|head -8|awk '$1 ~ /RX/ && $4 ~ /bytes/ || $1 ~ /TX/ && $4 ~ /bytes/ {print $0}'
RX packets 494598 bytes 38344433 (36.5 MiB)
TX packets 17025 bytes 1718505 (1.6 MiB)
[root@cPen_A ~]# ifconfig|head -8|awk '$1 ~ /RX/ && $4 ~ /bytes/ || $1 ~ /TX/ && $4 ~ /bytes/ {print $5}'
38372669
1719743
[root@cPen_A ~]# ifconfig|head -8|awk '$0 ~ /RX.*bytes|TX.*bytes/ {print $5}'
38476866
1744541
#注:当有&&或者||,&&(and)的优先级高
使用awk命令统计以r开头的用户数目,显示如下效果
[root@cPen_A ~]# cat /etc/passwd|awk -F: 'BEGIN{i=0} $1 ~ /^r/ {print $1;i++} END{print i}'
root
rpc
rpcuser
3
awk和shell变量交换的问题
1、使用 -v选项
2、使用双引号,但是awk内部的$0 $1等$符号前需要使用\转义
3、使用单引号,将变量引起来,然后前面加一个$符号再次引用变量的值,相当于取2次值
示例:使用 -v选项
[root@cPen_A ~]# sg="panjinhao"
[root@cPen_A ~]# echo $sg
panjinhao
[root@cPen_A ~]# echo|awk '{print $sg}'
[root@cPen_A ~]# echo|awk -v bsg=$sg '{print bsg}'
panjinhao
[root@cPen_A ~]# ls|awk -v bsg=$sg '{print bsg}'
panjinhao #注:ls 输出多行
panjinhao
……
panjinhao
[root@cPen_A lianxi]# vim test2.sh
awk -v var=$1 -F: '$1==var{print NR,$0}' /etc/passwd
[root@cPen_A lianxi]# bash test2.sh root
1 root:x:0:0:root:/root:/bin/bash
[root@cPen_A lianxi]# bash test2.sh sanchuang
21 sanchuang:x:1000:1000::/home/sanchuang:/bin/bash
#注:第1个$1 位置变量,第2个$1 第1个字段
示例:使用双引号,但是awk内部的$0 $1等$符号前需要使用\转义
[root@cPen_A lianxi]# mv="zhangjie"
[root@cPen_A lianxi]# useradd zhangjie_123
[root@cPen_A lianxi]# cat /etc/passwd|awk -F: "/^$mv/{print \$1,\$3}"
zhangjie_123 12358
示例:使用单引号,将变量引起来,然后前面加一个$符号再次引用变量的值,相当于取2次值
[root@cPen_A lianxi]# sg=3
[root@cPen_A lianxi]# awk -F: '/root/{print $1,$'$sg'}' /etc/passwd
root 0
operator 11
进程和进程之间通信的方式
1、共享内存
2、信号量
3、信号
4、管道
5、队列
6、Socket
[root@cPen_A lianxi]# cat /etc/shadow
第2个字段:密码字段
*操作系统自带的,没有密码的
!!用户建的,没有密码的
提示:密码字段为*、!!表示没有设置密码;密码字段为空说明密码被清除。
示例:没有设置密码的用户
[root@cPen_A lianxi]# cat /etc/shadow|awk -F: 'BEGIN{i=0}length($2)<=2{print $1,"没有设置密码";i++}END{print "一共有"i"个用户"}'
awk内置的函数
length()
int()
sqrt()
system()
String Functions
sub()
index()
length()
split()
示例:生成0-1之间随机数
[root@cPen_A lianxi]# echo |awk '{print rand()}'
0.237788
示例:产生0-100之间随机数
[root@cPen_A lianxi]# echo |awk '{print rand()*100}'
23.7788
[root@cPen_A lianxi]# echo |awk '{print int(rand()*100)}'
23
流控:流程控制
for
while
case
if
if语句
单分支
[root@cPen_A lianxi]# awk -F: '{if($1 ~ /\<...\>/)print $0}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
[root@cPen_A lianxi]# awk -F: '$1 ~ /\<.{3}\>/{print $0}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
双分支
[root@cPen_A lianxi]# awk -F: '{if($1 ~ /\<...\>/)print $0;else print "不符合要求"}' /etc/passwd
不符合要求
bin:x:1:1:bin:/bin:/sbin/nologin
/etc/passwd
$3是uid 用户的编号
如果用户的编号是0 --> 管理员
1~999 --> 程序用户
大于1000 --> 普通用户
最后统计出有多少管理员,多少程序用户,多少普通用户?
[root@cPen_A ~]# awk -F: 'BEGIN{x=0;y=0;z=0}{if($3=="0") {print $1,"管理员";x++} else if($3>=1 && $3<=999) {print $1,"程序用户";y++} else {print $1,"普通用户";z++}}END{print "管理员"x,"程序用户"y,"普通用户"z}' /etc/passwd
root 管理员
bin 程序用户
……
管理员1 程序用户25 普通用户40