目录
1、通配符
2、正则表达式
2.1、grep使用正则的语法
2.1.1、-i、-o、-n
2.1.2、 -A、-B、-C
2.1.3、-v(按行取反)和中括号中尖括号(对单个字符取反,更加细节一点)
2.1.4、-r
2.2、单词以什么开头以什么结尾
2.2.1、\s表示一个空白(空格或者tab)
2.3、正则表达式由下列元素构成
2.3.1、显示有效行
2.4、通用修饰符
2.4.1、转义字符
2.5、正则表达式分组
2.6、正则练习
2.6.1、写一个邮箱的正则
2.7、关于时间的正则表达
3、awk
3.1、分隔符
3.1.1、OFS输出分隔符
3.1.2、FS输入分隔符
3.2、awk命令的基本语法
3.2.1、只有模式没有动作结果的awk命令和grep的作用一样
3.2.2、$NF和$NR
3.2.3、awk命令的操作符( 模糊匹配和精准匹配)
3.2.4、awk基本命令示例
3.3、awk命令的内部变量
3.3.1、内部变量的使用实例
3.4、linux可以生成csv文件,然后传入windows里边,用excel答案开
3.5、小练习(含有watch和split的使用方法)
3.6、-F使用小技巧
4、awk命令引用shell变量问题
4.1、-v,引入shell变量
4.2、使用双引号,但是$符号需要转义
5、awk内置函数
5.1、length
5.2、toupper和tolower
5.3、split
5.4、substr
6、流控(if和for)
6.1、if
6.1.1、单分支和双分支
6.1.2、多分支
6.1.3、总结
6.2、for
6.2.1、自增(awk的行求和)
7、awk数组
7.1、一列中有重复的值,但是对应的另一列的内容一直不一样,想要实现累加功能。
7.2、awk数组小练习
7.2.1、输出文本的第一行和最后一行
7.2.2、已知一台服务器netstat -an 输出格式如下
7.2.3、计算nginx日志
8、分析操作系统自带的脚本(/etc/init.d/functions和/etc/init.d/network)
8.1、functions
8.2、bash自带的处理字符串
1、通配符
################# 只需要筛选出满足[]中至少一个元素的行出来就行了
[root@fttswlp grep]# cat passwd |tail|egrep "[azxhoui\-]"
wujin_son:x:7793:7793::/home/wujin_son:/bin/bash
songqingshu_son:x:7794:7794::/home/songqingshu_son:/bin/bash
wangchen_son:x:7795:7795::/home/wangchen_son:/bin/bash
cali:x:7796:7796::/home/cali:/bin/bash
dengjz:x:7797:7790::/home/dengjz:/bin/bash
xiaohui:x:7798:7797::/home/xiaohui:/bin/bash
tcpdump:x:72:72::/:/sbin/nologin
test:x:7799:7799::/home/test:/bin/bash
mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
xiaohui\hhh:x:7798:7797::/home/xiaohui:/bin/bash
######## {} 是扩展正则,所以需要使用"egrep"或者"grep -E"
[root@fttswlp grep]# cat passwd |tail|egrep "[azxhoui\-]{6}"
xiaohui:x:7798:7797::/home/xiaohui:/bin/bash
xiaohui\hhh:x:7798:7797::/home/xiaohui:/bin/bash
2、正则表达式
基本正则:^ $ . *
扩展正则:| + ? {}
2.1、grep使用正则的语法
用途:使用正则表达式搜索文本,并把匹配的行打印出来
格式:grep [选项] ... 模式 目标
- -v,反转查找,输出和模式不相符的行
- -An,同时显示符合条件行的后面的n行
- -Bn,同时显示符合条件行的前面的n行
- -Cn,同时显示符合条件行的前后的n行
- -E,支持扩展正则表达式
- -o,仅显示匹配模式的字符串
- -f,根据文件内容进行匹配
- -i,不区分大小写
- -n,显示行号
- -c,计算找到的符合行的次数
- -r,递归查找,查找出文件夹里的所有的文件和文件夹里文本文件都查找一遍
#试验文件
[root@fttswlp grep]# cat test
wujin_son:x:7793:7793::/home/wujin_son:/bin/bash
songqingshu_son:x:7794:7794::/home/songqingshu_son:/bin/bash
wangchen_son:x:7795:7795::/home/wangchen_son:/bin/bash
cali:x:7796:7796::/home/cali:/bin/bash
CALI:x:7796:7796::/home/cali:/bin/bash
dengjz:x:7797:7790::/home/dengjz:/bin/bash
2.1.1、-i、-o、-n
[root@fttswlp grep]# grep -i cali test
cali:x:7796:7796::/home/cali:/bin/bash
CALI:x:7796:7796::/home/cali:/bin/bash
[root@fttswlp grep]# grep -i -o cali test
cali
cali
CALI
cali
[root@fttswlp grep]# grep -i -o -n cali test
4:cali
4:cali
5:CALI
5:cali
2.1.2、 -A、-B、-C
[root@fttswlp grep]# grep -A 1 wangchen_son test
wangchen_son:x:7795:7795::/home/wangchen_son:/bin/bash
cali:x:7796:7796::/home/cali:/bin/bash
[root@fttswlp grep]# grep -B 1 wangchen_son test
songqingshu_son:x:7794:7794::/home/songqingshu_son:/bin/bash
wangchen_son:x:7795:7795::/home/wangchen_son:/bin/bash
[root@fttswlp grep]# grep -C 1 wangchen_son test
songqingshu_son:x:7794:7794::/home/songqingshu_son:/bin/bash
wangchen_son:x:7795:7795::/home/wangchen_son:/bin/bash
cali:x:7796:7796::/home/cali:/bin/bash
2.1.3、-v(按行取反)和中括号中尖括号(对单个字符取反,更加细节一点)
[root@fttswlp grep]# grep -v wangchen_son test
wujin_son:x:7793:7793::/home/wujin_son:/bin/bash
songqingshu_son:x:7794:7794::/home/songqingshu_son:/bin/bash
cali:x:7796:7796::/home/cali:/bin/bash
CALI:x:7796:7796::/home/cali:/bin/bash
dengjz:x:7797:7790::/home/dengjz:/bin/bash
##########
[root@fttswlp grep]# cat test |egrep -v "[0-Z]"
[root@fttswlp grep]# cat test |egrep "[^0-Z]"
wujin_son:x:7793:7793::/home/wujin_son:/bin/bash
songqingshu_son:x:7794:7794::/home/songqingshu_son:/bin/bash
wangchen_son:x:7795:7795::/home/wangchen_son:/bin/bash
cali:x:7796:7796::/home/cali:/bin/bash
CALI:x:7796:7796::/home/cali:/bin/bash
dengjz:x:7797:7790::/home/dengjz:/bin/bash
2.1.4、-r
[root@fttswlp grep]# grep -r "dengjz" .
./passwd:dengjz:x:7797:7790::/home/dengjz:/bin/bash
./test:dengjz:x:7797:7790::/home/dengjz:/bin/bash
2.2、单词以什么开头以什么结尾
[root@fttswlp grep]# cat name.txt
liuyifei yifeiliu feiliuyi
[root@fttswlp grep]# cat name.txt |grep "\bliu"
liuyifei yifeiliu feiliuyi
[root@fttswlp grep]# cat name.txt |grep "liu\b"
liuyifei yifeiliu feiliuyi
[root@fttswlp grep]# cat name.txt |grep "\bliuyifei\b"
liuyifei yifeiliu feiliuyi
2.2.1、\s表示一个空白(空格或者tab)
[root@fttswlp grep]# cat name.txt
liuyifei yifeiliu feiliuyi
zhou jielun lin junjie
[root@fttswlp grep]# cat name.txt |egrep "zhou\sjielun"
zhou jielun lin junjie
[root@fttswlp grep]# cat name.txt |egrep "lin\sjunjie"
### 表示两个以上的空白
[root@fttswlp grep]# cat name.txt |egrep "lin\s{2,}junjie"
zhou jielun lin junjie
[root@fttswlp grep]# cat name.txt |egrep "lin\s+junjie"
zhou jielun lin junjie
2.3、正则表达式由下列元素构成
2.3.1、显示有效行
[root@fttswlp grep]# cat /etc/ssh/sshd_config |egrep -v "^#|^$"
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication yes
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
UsePAM yes
X11Forwarding yes
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem sftp /usr/libexec/openssh/sftp-server
2.4、通用修饰符
- "?":表示前边的字符出现0个或者1个(扩展)
- "*":表示前边的字符出现0个或者多个
- "+":表示前边的字符出现1个以上(扩展)
- {n}:表示前边的字符出现n个
- {n, m}:表示前边的字符出现n个到m个
- .*:表示任意字符
2.4.1、转义字符
若是想要把元字符变成普通的没有特殊含义的字符,那么就是要加上"\",若是没有用的话,那么就用"\\"
2.5、正则表达式分组
f(oo)*:表示(oo)出现n次 (oo|ee){2}:表示oo或者ee出现两次
2.6、正则练习
# 2
[root@fttswlp grep]# egrep "ftp|mail" passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
# 3
[root@fttswlp grep]# egrep "^[^rfm]" passwd
[root@fttswlp grep]# egrep -v "^[rfm]" passwd
# 4
[root@fttswlp grep]# grep "bash$" passwd
# 5
[root@fttswlp grep]# egrep -v "^#|^$" /etc/login.defs
# 6(若是找不出来的话,可以换个文件或者这个查找的字母个数变小点)
[root@fttswlp grep]# egrep "\b[a-Z]{16}\b" /var/log/messages
# 7
[root@fttswlp grep]# egrep ".*liu.*bash$" passwd
# 9
[root@fttswlp grep]# egrep "\b[0-9]{2}\b" /etc/ssh/ssh_config
# 10(因为这是按行输出)
[root@fttswlp grep]# egrep "[^0-Z]" /etc/ssh/ssh_config
# 11
[root@fttswlp rough_book]# egrep -v "[0-9]" /etc/ssh/ssh_config
# 14
[root@fttswlp grep]# egrep "[a-Z]+://([0-Z]+\.){2}[0-Z]+(\.[0-Z]+)?" web.txt
# 16 C类IP地址的正则表达式
[root@fttswlp ~]# netstat -anplut|egrep "(19[2-9]|2[01][0-9]|22[0-3])(\.([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])){3}"
tcp 0 44 192.168.29.128:22 192.168.29.1:52496 ESTABLISHED 1675/sshd: root@pts
# 自己可以尝试一下写出A、B类的正则表达式
2.6.1、写一个邮箱的正则
2.7、关于时间的正则表达
下面的文件只是从历史的数据文件中分析的,不是实时的文件
练习1:
[root@fttswlp time]# cat access.log |egrep "18/Dec/2021:16:5[4-8]:[0-5][0-9]"|awk '{sum+=$10}END{print sum}'
482338
# awk在处理数据,是按行处理的,每次都把数据给sum(这个sum只是一个变量名)。最后用"END"打印最后的值
# 这样可以看的更加的清楚,只是加了一些标识,让我们更加了解这个过程
[root@fttswlp time]# cat access.log |egrep "18/Dec/2021:16:5[4-8]:[0-5][0-9]"|awk 'BEGIN{print "start"}{print "行号"NR;sum+=$10;print sum}END{print sum}'
练习2:
[root@fttswlp time]# cat scan_day.sh
#!/bin/bash
>min2.txt
for i in {00..24}
do
for j in {00..59}
do
if cat access.log |egrep "18/Dec/2021:$i:$j:[0-5][0-9]" >>/dev/null
then
echo "$i:$j">>min2.txt
cat access.log |egrep "18/Dec/2021:$i:$j:[0-5][0-9]"|awk '{a+=$10}END{print a}' >>min2.txt
fi
done
done
2.算出2022年7月份里的每一个分钟的流量,具体日志文件格式如下:
2022-7-1 00:01:01 78
2022-7-1 00:01:04 89
2022-7-1 00:03:01 178
2022-7-1 00:03:05 890
2022-7-2 00:03:01 178
2022-7-3 00:03:05 890
....
2022-7-30 00:03:01 178
2022-7-31 00:07:05 8900可自行编辑数据
[root@fttswlp 9_74]# awk '{time[$1,substr($1,5,1)substr($2,1,5)]+=$3}END{for (i in time)print i,time[i]}' test.txt |sort -n -k 3 -t -
2022-7-1-00:01 167
2022-7-1-00:03 1068
2022-7-2-00:03 178
2022-7-3-00:03 890
2022-7-5-10:03 890
2022-7-5-12:03 890
2022-7-5-19:03 5213
2022-7-6-20:03 800
2022-7-10-12:08 900
2022-7-11-16:33 5130
2022-7-30-00:03 178
2022-7-31-00:07 8900
3、awk
文本三剑客之一:awk
awk的引入:
[root@fttswlp awk]# cat tongji.txt |awk '{pro[$1] += $3}END{ for (i in pro) print i, pro[i] }' 河南 3 江西 9 山东 12 # "cat tongji.txt |awk '{pro[$1] += $3}"这段命令会成成pro,pro={'山东':12,"河南":3,"江西":9}。然后后边又使用了for循环
上面这个结果是利用了数组的性质
用for循环执行数组的输出
3.1、分隔符
3.1.1、OFS输出分隔符
[root@fttswlp time]# awk -F : 'OFS="#"{print$1,$3}' /etc/passwd
dengjz#7797
xiaohui#7798
tcpdump#72
test#7799
mysql#27
3.1.2、FS输入分隔符
[root@fttswlp time]# awk 'BEGIN{FS=":"}OFS="#"{print$1,$3}' /etc/passwd
这个命令和上边的效果是一样的
3.2、awk命令的基本语法
3.2.1、只有模式没有动作结果的awk命令和grep的作用一样
[root@fttswlp ~]# cat /etc/passwd | awk '/feng/'
califeng:x:1008:1008::/home/califeng:/bin/bash
我们都知道awk的命令中要使用单引号,那么可不可以使用双引号呢?答案是可以的,但是要加入一些东西。
[root@fttswlp ~]# w|awk '{print $2}'
up
TTY
pts/0
[root@fttswlp ~]# w|awk "{print \$2}"
up
TTY
pts/0
# 匹配第一个字段中以h开头的行
[root@fttswlp ~]# awk -F : '/^h/{print $1,$7}' /etc/passwd
halt /sbin/halt
3.2.2、$NF和$NR
$NF取最后一个;$NR取最开始的一个
[root@fttswlp ~]# awk -F [/:] '{print $1,$7,$NF,$(NF-1)}' /etc/passwd | head -5
root root bash bin
bin bin nologin sbin
daemon sbin nologin sbin
adm var nologin sbin
lp var nologin sbin
3.2.3、awk命令的操作符( 模糊匹配和精准匹配)
模糊匹配(~):匹配的行要是包含关系
# 第一段要以数字结尾
[root@fttswlp ~]# awk -F : '$1 ~ /[0-9]$/{print $1,$7}' /etc/passwd
cali123 /bin/bash
fan1 /bin/bash
fan2 /bin/bash
# 第一段要以数字结尾且第三个字段要大于1005
[root@fttswlp ~]# awk -F : '$1 ~ /[0-9]$/ && $3>1005{print $1,$7,$3}' /etc/passwd
cali123 /bin/bash 1009
fan1 /bin/bash 7800
fan2 /bin/bash 7801
# 第三段要是3位数的
[root@fttswlp ~]# awk -F : '$3 ~ /\<[0-9]{3}\>/ {print $1,$3}' /etc/passwd
systemd-network 192
polkitd 999
chrony 998
nginx 997
精准匹配(==):匹配的行要一摸一样
[root@fttswlp ~]# awk -F : '$1 == "fan1" && $3>1005{print $1,$7,$3}' /etc/passwd
fan1 /bin/bash 7800
3.2.4、awk基本命令示例
# 找出100以内,以1开头的或者能够被5整除的数
[root@fttswlp ~]# seq 100 |awk '$1 % 5 == 0 || $1 ~ /^1/{print $1}'
[root@fttswlp ~]# cat /etc/passwd|awk -F : 'BEGIN{i=1}$1 ~ /user/ || $3>1000{i++;print $1,$3}END{print "出现的次数为" i}'
# 显示/etc/passwd文件中第一段有user或者第三段的数值大于1000的行,并统计这些行出现了多少次
3.3、awk命令的内部变量
3.3.1、内部变量的使用实例
[root@fttswlp ~]# awk 'NR ~ /^[0-9]$/ {print NR,$o}' /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
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
3.4、linux可以生成csv文件,然后传入windows里边,用excel答案开
[root@fttswlp rough_book]# awk -F : 'OFS="," {print $1,$3,$4}' /etc/passwd >name.csv
[root@fttswlp rough_book]# cat name.csv |head -5
root,0,0
bin,1,1
daemon,2,2
adm,3,4
lp,4,7
###### 然后可以把这个文件传到Windows里边,然后再用excel打开。会自动按照","去进行分列
3.5、小练习(含有watch和split的使用方法)
提示1:例题7中使用了split函数
提示2:第八题中的入站流量和出站流量为,下图中的部分。且答案可以用watch来进行实时监控
# 2
[root@fttswlp rough_book]# awk -F : 'NR==5 || NR==10{print NR,$1}' /etc/passwd
5 lp
10 operator
# 3
[root@fttswlp rough_book]# cat /etc/passwd|awk -F : '{print $(NF-1)}'
# 4
[root@fttswlp rough_book]# awk -F : 'NR>=5 && NR<=10{print NR,$1}' /etc/passwd
# 5
[root@fttswlp rough_book]# awk -F : '$7 !~ /bash/ {print NR,$7}' /etc/passwd
# 6
[root@fttswlp rough_book]# awk -F : 'NR ~ /5$/ {print NR,$0}' /etc/passwd
# 7
[root@fttswlp rough_book]# ip add|awk '/inet.*ens[0-9]+/{split($2,a,"/");print a[1]}'
# 8
[root@fttswlp rough_book]# ifconfig|awk 'NR==5||NR==7{print $5}' # 这个只是看那一瞬间进出站的流量大小
# 若是想要实时监控每隔2秒的流量的变化,可以用下面这个命令(用watch来进行监控)
[root@fttswlp rough_book]# watch -n 2 -d "ifconfig|awk 'NR==5{print $5}'"
# -n,是间隔时间;-d,是看数据的差异
# 9
[root@fttswlp rough_book]# awk -F : 'BEGIN{i=0} /^r/{print $0;i++} END{print i}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
1
3.6、-F使用小技巧
若是在几个字段中结构如下所示
$1 $2:$3
我们想要截取$1和$3,若是我们直接使用awk -F "[ :]" 文件名,是找不到结果的,因为有多个空格。但若是我们这么使用awk -F "[ :]+" 文件名,那么是可以打印出来我们想要的结果的。
4、awk命令引用shell变量问题
4.1、-v,引入shell变量
[root@fttswlp ~]# name=fbb
[root@fttswlp ~]# echo |awk -v sg=$name '{print sg}'
fbb
4.2、使用双引号,但是$符号需要转义
注意:命令被shell解析,有些地方需要考虑转义
[root@fttswlp ~]# mn=zhaoliying
[root@fttswlp ~]# cat /etc/passwd|awk -F: "\$1 ~ /$mn/{print NR,\$0}"
50 zhaoliying1:x:7802:7805::/home/zhaoliying1:/bin/bash
51 zhaoliying2:x:7803:7806::/home/zhaoliying2:/bin/bash
# 注意shell里面的变量($mn)不需要转义,因为它需要被shell解析;但是$1和$0需要加入转义,因为他们不要被shell进行解析。只需要awk对他们进行解析就行了。
5、awk内置函数
length
5.1、length
作用:用来统计字符的多少
# 可以用来统计用户中没有设置密码的用户数量和具体的用户。只要/etc/shadow里面第二个字段的长度小于2就表明没有设置密码。
[root@fttswlp ~]# cat /etc/shadow|awk -F: 'BEGIN{i=0}length($2) <=2 {print "用户没有设置密码:"$1;i++}END{print "有"i"个用户没有设置密码"}'
用户没有设置密码:xiaohui
用户没有设置密码:tcpdump
用户没有设置密码:mysql
有40个用户没有设置密码
# 显示用户名长度在5到10之间的用户,并且使用shell为bash,uid大于500
[root@fttswlp ~]# cat /etc/passwd|awk -F: 'length($1)>=5 && length($1) <=10 && $3>500 && /bash$/{print $0}'
chenxw:x:1004:1004::/home/chenxw:/bin/bash
caohx:x:1005:1005::/home/caohx:/bin/bash
zhangjian:x:1006:1006::/home/zhangjian:/bin/bash
5.2、toupper和tolower
作用:转化为大小写
[root@fttswlp ~]# cat /etc/passwd|awk -F: 'length($1)>=5 && length($1) <=10 && $3>500 && /bash$/{print NR,toupper($1)}'
21 CHENXW
22 CAOHX
5.3、split
注意:用split切片出来的数组的下标,是从1开始的。
[root@fttswlp ~]# cat /etc/passwd|awk -F: 'length($1)>=5 && length($1) <=10 && $3>500 && /bash$/{split($7,s,"/");print NR,s[3]}'
21 bash
22 bash
5.4、substr
作用:单独截取某个字段的单独几个字符
# 选取第一个字段,只截取第一个到第四个字符
[root@fttswlp ~]# cat /etc/passwd|awk -F: 'length($1)>=5 && length($1) <=10 && $3>500 && /bash$/{print NR,substr($1,1,4)}'
21 chen
22 caoh
###### substr($1,n,m):截取下标为n元素后面的m个元素(包括n)
6、流控(if和for)
6.1、if
分为单分支、双分支和多分支
6.1.1、单分支和双分支
[root@fttswlp ~]# ifconfig|awk 'NR==5||NR==7{if($1 == "RX")print "接受的流量为:"$5;else print "发送的流量为:"$5}'
接受的流量为:280732
发送的流量为:218441
6.1.2、多分支
# 利用awk的if多分支判断用户的类型,root显示为管理员
[root@fttswlp ~]# awk -F : '{if($3==0)print $1"是管理员";else if($3>0 && $3<500) print $1"是系统用户";else if($3>=500 && $3<=60000)print $1,"是普通用户";else print $1"是其他用户"}' /etc/passwd|head -5
root是管理员
bin是系统用户
daemon是系统用户
adm是系统用户
lp是系统用户
#### 并统计各用户数量
[root@fttswlp rough_book]# cat /etc/passwd|head -5| awk -F : '{if($3==0){print $1"是超级用户";cj++;}else if($3>0 && $3<1100) {print $1"是系统用户";xi++;}else {print $1"是普通用户";pt++}}END{print "超级用户为:"cj,"系统用户为:"xi,"普通用户为:"pt}'
root是超级用户
bin是系统用户
daemon是系统用户
adm是系统用户
lp是系统用户
超级用户为:1 系统用户为:4 普通用户为:
这个是上面那个例子的进阶版
6.1.3、总结
if语句后面执行多个命令的时候,使用{}括起来,最后的命令接;结尾。外面的else if和else前面不需要接;了。
6.2、for
格式为:
6.2.1、自增(awk的行求和)
# 这里的$i,是对应的一行的列序号
[root@fttswlp ~]# seq -s ' ' 10|awk '{for (i=1;i<=NF;i++) sum+=$i}END{print sum}'
55
若是列求和的话,不需要使用for循环
[root@fttswlp ~]# seq 10 |awk '{sum+=$1}END{print sum}'
55
7、awk数组
作用:累加(行累加和列累加)和统计功能
shell编程中的数组,类似于python中的字典。用一个字段做key,另一个字段做value,存放数据到数组,取数据的时候使用for循环。
[root@fttswlp ~]# cat /etc/passwd|awk -F: '{user[$1]=$3 }END{for (i in user) print i,user[i]}'
adm 3
sync 5
mail 8
7.1、一列中有重复的值,但是对应的另一列的内容一直不一样,想要实现累加功能。
# 该文件大致内容如下所示:
[root@fttswlp linux]# cat rough_book/time/access.log
192.168.0.237 - - [18/Dec/2021:17:02:21 +0800] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36"
# 统计该文件中IP地址获得的流量大小。我们利用了shell数组中会自动去重的功能。
# 对第二列进行降序排序
[root@fttswlp linux]# cat rough_book/time/access.log|awk '{traffic[$1]+=$10}END{for (i in traffic)print i,traffic[i]}'|sort -k2 -nr
192.168.0.237 489358
192.168.0.13 482846
192.168.0.251 2340
192.168.0.7 1170
192.168.0.69 1170
192.168.0.37 1170
192.168.0.30 1170
192.168.0.208 1170
192.168.0.14 1170
[root@fttswlp awk]# awk 'NR>1{cz[$1]+=$2}END{for (i in cz)print i,cz[i]}' gamebill.txt |sort -k2 -nr
li 1329
feng 650
zhang 450
7.2、awk数组小练习
7.2.1、输出文本的第一行和最后一行
[root@fttswlp awk]# cat /etc/passwd|awk 'NR==1{print NR,$0}END{print NR,$0}'
1 root:x:0:0:root:/root:/bin/bash
51 zhaoliying2:x:7803:7806::/home/zhaoliying2:/bin/bash
7.2.2、已知一台服务器netstat -an 输出格式如下
2:
cat abc.txt|awk 'NR>1{split($5,ip,":");sc[ip[1]]+=1}END{for (i in sc)print "ip:"i,"count:"sc[i]}'|head
3.
cat abc.txt|awk 'NR >1 1&& $6 ~/EST/{split($5,ip,":");sc[ip[1]]+=1}END{for (i in sc)print "ip:"i,"count:"sc[i]}'
# 另外一种方法:
cat abc.txt|awk 'NR > 1&& $6 ~/EST/{split($5,ip,":");print ip[1]}'|sort|uniq -c|sort -nr
# 统计一下状态的数量
cat abc.txt|awk 'NR>1{state[$6]+=1}END{for (i in state)print "状态为:"i,"数量为:"state[i]}'
7.2.3、计算nginx日志
1.
cat nginx.txt|awk -F "|" '{t[substr($1,1,16)]+=$6}END{for (i in t) print i,t[i]}'
2. # 思路:使用时间+url一起做key,然后统计次数
cat nginx.txt|awk -F "[|?]" '{t[substr($1,1,16)$4]+=1}END{for (i in t) print i,t[i]}'
8、分析操作系统自带的脚本(/etc/init.d/functions和/etc/init.d/network)
这些文件在"/etc/init.d"文件夹里面
[root@fttswlp rough_book]# cd /etc/init.d
[root@fttswlp init.d]# ls
functions netconsole network README
8.1、functions
# 分析第7行到第23行
6
7 TEXTDOMAIN=initscripts # 赋值一个变量
8
9 # Make sure umask is sane
10 umask 022
11
12 # Set up a default search path.
13 PATH="/sbin:/usr/sbin:/bin:/usr/bin"
14 export PATH
15
# -ne,not equal不等于;-a,and;-z,判断后面着变量的长度是否为0;最后一个"\"为续行符
16 if [ $PPID -ne 1 -a -z "$SYSTEMCTL_SKIP_REDIRECT" ] && \
# -d,判断后面的路径是否为目录。
17 [ -d /run/systemd/system ] ; then
# "$0",脚本文件的名字
18 case "$0" in
# 如果这个脚本文件在下面的这里路径中,那么久设置_use_systemctl=1
19 /etc/init.d/*|/etc/rc.d/init.d/*)
20 _use_systemctl=1
21 ;;
22 esac
23 fi
# 分析25到56行
25 systemctl_redirect () { # 定义一个函数名
26 local s
27 local prog=${1##*/} # 对第一个位置变量,从左边开始删除直到遇到最后一个/为止
28 local command=$2
29 local options=""
30
31 case "$command" in
32 start)
33 s=$"Starting $prog (via systemctl): "
34 ;;
35 stop)
36 s=$"Stopping $prog (via systemctl): "
37 ;;
38 reload|try-reload)
39 s=$"Reloading $prog configuration (via systemctl): "
40 ;;
41 restart|try-restart|condrestart)
42 s=$"Restarting $prog (via systemctl): "
43 ;;
44 esac
45
# 如果这个变量不为0
46 if [ -n "$SYSTEMCTL_IGNORE_DEPENDENCIES" ] ; then
47 options="--ignore-dependencies"
48 fi
49
# 如果systemctl show "$prog.service"执行没有成功,
50 if ! systemctl show "$prog.service" > /dev/null 2>&1 || \
# systemctl show -p LoadState "$prog.service" | grep -q 'not-found' ,或者,这条命令没有找到,那么就执行下面的语句
51 systemctl show -p LoadState "$prog.service" | grep -q 'not-found' ; then
52 action $"Reloading systemd: " /bin/systemctl daemon-reload
53 fi
54
# 这里的action是一个函数
55 action "$s" /bin/systemctl $options $command "$prog.service"
56 }
624 is_ignored_file() {
625 case "$1" in
626 *~ | *.bak | *.old | *.orig | *.rpmnew | *.rpmorig | *.rpmsave)
627 return 0
628 ;;
629 esac
630 return 1
631 }
674 for file in /usr/lib/sysctl.d/*.conf ; do
# is_ignored_file,是一个函数
675 is_ignored_file "$file" && continue
676 [ -f /run/sysctl.d/${file##*/} ] && continue
677 [ -f /etc/sysctl.d/${file##*/} ] && continue
# test -f,一样是判断文件是否存在
678 test -f "$file" && sysctl -e -p "$file" >/dev/null 2>&1
679 done
680 for file in /run/sysctl.d/*.conf ; do
681 is_ignored_file "$file" && continue
682 [ -f /etc/sysctl.d/${file##*/} ] && continue
683 test -f "$file" && sysctl -e -p "$file" >/dev/null 2>&1
684 done
685 for file in /etc/sysctl.d/*.conf ; do
686 is_ignored_file "$file" && continue
687 test -f "$file" && sysctl -e -p "$file" >/dev/null 2>&1
688 done
689 sysctl -e -p /etc/sysctl.conf >/dev/null 2>&1
690 fi
691 }
8.2、bash自带的处理字符串
# a=www.bai.com
[root@fttswlp ~]# echo ${#a} # 统计a中的字符个数
11
[root@fttswlp ~]# echo ${a:3} # $a中从第三个开始取值到结束
.bai.com
[root@fttswlp ~]# echo ${a:3:2} # $a中从第三个开始取两个字符
.b
[root@fttswlp ~]# echo ${a: -1} # 取最后一个字符
m
[root@fttswlp ~]# echo ${a#*.} # 从左边开始删除直到遇到.为止
bai.com
[root@fttswlp ~]# echo ${a##*.} # 从左边开始删除直到遇到最后一个.为止
com
[root@fttswlp ~]# echo ${a%.*} # 从右边开始删除知道遇到第一个.为止
www.bai
[root@fttswlp ~]# echo ${a%%.*} # 从右边开始删除直到遇到最后一个.为止
www
[root@fttswlp ~]# echo ${a/www/hhh} # 将变量a中的第一个www替换成hhh
hhh.bai.com
#######
[root@fttswlp ~]# a=www.www.123
[root@fttswlp ~]# echo ${a//www/hhh} # 将变量a中的所有www替换成hhh
hhh.hhh.123