[轻松学会shell编程]-3、grep、正则表达式、awk的详细用法、分析系统自带的两个文件(functions和network)

目录

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FanMY_71

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值