• 欢迎访问显哥博客,本网站纯属学习技术,绝无商业用途,欢迎小伙伴们共同学习!研究技术!QQ:52249909 加我QQ
  • 世界75亿人,这么小的概率,能认识你,是我一生的幸运,不妨加个QQ接触一下:52249909 加我QQ

Shell脚本编程学习——Shell正则表达式应用【显哥出品,必为精品】

Shell编程 lixian 5年前 (2020-05-08) 1850次浏览 0个评论 扫描二维码
文章目录[隐藏]

一、正则表达式概述

1. 什么是正则表达式

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“regex”,单数有regexp、regex,复数有regexps、regexes、regexen。
正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

2.什么要使用正则表达式

在工作中,我们时刻面对着大量的日志,程序,以及命令的输出。迫切的需要过滤我们需要的一部分内容,甚至是一个字符串。比如: 现在有一个上千行的文件,我们仅需要其中以”root”开头的行,怎么办? 此时就需要使用到正则表达式的规则来筛选想要的内容。
Shell脚本编程学习——Shell正则表达式应用【显哥出品,必为精品】

二、正则表达式规则

1.常见通配符及特殊符号介绍

符号 描述
. 当前目录
.. 当前目录的上一级目录
当前目录的上一次所在的目录
~ 家目录
# 注释,注释后面的命令不会被执行,超级管理员的命令提示符
$ 引用变量,数组,普通用户命令提示符
非,取反
& 将程序放到后台运行
&& 前面的命令执行成功,才会执行后面的命令
|| 前面的命令执行失败,才会执行后面的命令
| 管道符,将前面的命令的输出结果以标准输入的方式给后面的命令
\ 转义字符,取消一些特殊字符的含义,换行,一条命令分割多行书写
$()或“ 优先执行里面的命令,将命令的执行结果输出给外面的命令
* 所有,任意
匹配任意一个字符且只能是一个,必须是一个
[] 匹配中任意一个字符
[^]排除中括号中任意一个字符
{} 生成序列,整体
() 整体
单引号,强引用
“” 双引号,弱引用
命令的分隔符

2.基础正则表达式

符号 描述
^ 以什么为开头
$ 以什么结尾
^$ 空行
. 任意一个字符,排除换行符
* 匹配前面的字符出现0次或者多次
.* 所有
\ 转义字符,将一些特殊的字符取消特殊的含义
[] 匹配中括号中任意一个字符
[^] 排除中括号中任意一个字符
[0-9] 所有数字
[a-Z] 所有字母

3.扩展正则

符号 描述
+ 匹配前面的字符出现1次或者多次
匹配前面的字符出现0次或者1次
| 或者
() 创建一个用户匹配的字符串,后向引用
{n} n=数字,匹配前面的字符出现n次
{n,} 匹配前面的字符至少出现n次,最大没有限制
{n,m} 匹配前面的字符出现至少n次,最大m次(n
{,m} 匹配前面的字符至少出现0次,最多m次

4.特殊字符

符号 描述
[[:upper:]] 所有大写字母
[[:lower:]] 所有小写字母
[[:alpha:]] 所有字母
[[:digit:]] 所有数字
[[:alnum:]] 所有数字和字母
[[:space:]] 空白字符
[[:punct:]] 所有特殊字符 标点符号

三、正则表达式之Grep文本过滤实例

#以root开头
[root@xian /server/scripts]# grep '^root' passwd    
root:x:0:0:root:/root:/bin/bash

#以h结尾
[root@xian /server/scripts]# grep 'h$' passwd   
root:x:0:0:root:/root:/bin/bash
aaa5:x:1001:1001::/home/aaa5:/bin/bash

#匹配空行并显示行号
[root@xian /server/scripts]# grep -n '^$' passwd  
27:
28:

#匹配所有行,包括字符
[root@xian /server/scripts]# grep -n '.*' passwd    
。。。
。。。
。。。
24:mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
25:nginx:x:998:996:Nginx web server:/var/lib/nginx:/sbin/nologin
26:aaa5:x:1001:1001::/home/aaa5:/bin/bash
27:
28:

#过滤所有空白字符
[root@xian /server/scripts]# grep -n '^[[:space:]]*$' passwd
27:
28:

#过滤所有特殊符合或者标点符号 (如  /  $ % @ & ^ * ! . , :等  )
[root@xian /server/scripts]# grep '[[:punct:]]' passwd
root:x:0:0:root:/root:/b!in/bash
bin:x:1$:1:bin:/bin:/sb@in/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/l&&,pd:/sbin/nologin
sync:x:5:0:sync:/sbin:/b*in./sync
shutdown:x:6:0:shutdow#n:/sb/in:/sbin/shutdown

#匹配以a或者b开头的行
[root@xian /server/scripts]# grep -E '^[ab]' passwd  
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
aaa5:x:1001:1001::/home/aaa5:/bin/bash

#统计文件中所有字母出现的次数,自出从大到小进行排列
[root@xian /server/scripts]# grep -o '[a-Z]' passwd |sort |uniq -c | sort -nr |head   
    103 n
     82 o
     75 i
     70 s
     50 b
     45 a
     43 l
     41 r
     37 e
     32 t

#统计文件中所有单词出现的次数,次数从大到小进行排列
[root@xian /server/scripts]# egrep -o '[a-Z]+' passwd |sort |uniq -c |sort -nr |head  
     27 sbin
     26 x
     21 nologin
     11 var
      6 bin
      5 lib
      4 User
      4 root
      3 sync
      3 spool
[root@xian /server/scripts]# grep -o '[a-Z]*' passwd |sort |uniq -c |sort -nr |head 
     27 sbin
     26 x
     21 nologin
     11 var
      6 bin
      5 lib
      4 User
      4 root
      3 sync
      3 spool

#匹配字符出现0次或0次以上 (没有匹配到的行也显示出来了)
[root@xian /server/scripts]# grep  'l*' 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
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

#匹配字符出现1次或1次以上 (只显示匹配到的行)
[root@xian /server/scripts]# grep -E  'l+' passwd
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
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin

#匹配字符出现0次或0次以上 (一个字符串中,并不是一行)
[root@xian /server/scripts]# grep -o  'o*' passwd
oo
oo
oo
o
o
o
o
oo
o

#匹配字符出现0次或1次  (一个字符串只出现0次或1次)
[root@xian /server/scripts]# grep -Eo  'o?' passwd
o
o
o
o
o
o
o
o
o
o
o

#过滤多个字符串开头的行 (或者的意思)
[root@xian /server/scripts]# grep '^nginx' passwd
nginx:x:998:996:Nginx web server:/var/lib/nginx:/sbin/nologin
[root@xian /server/scripts]# grep -E '^nginx|^sync' passwd
sync:x:5:0:sync:/sbin:/bin/sync
nginx:x:998:996:Nginx web server:/var/lib/nginx:/sbin/nologin
[root@xian /server/scripts]# grep -E '^(mail|nginx|sync)' passwd
sync:x:5:0:sync:/sbin:/bin/sync
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
nginx:x:998:996:Nginx web server:/var/lib/nginx:/sbin/nologin

#匹配数字出现2次
[root@xian /server/scripts]# grep -Ew '[0-9]{2}' passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin

#匹配数字出现4次
[root@xian /server/scripts]# grep -Ew '[0-9]{4}' passwd
aaa5:x:1001:1001::/home/aaa5:/bin/bash

#匹配数字出现最少3次最多4次
[root@xian /server/scripts]# grep -Ew '[0-9]{3,4}' passwd
games:x:12:100:games:/usr/games:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
nginx:x:998:996:Nginx web server:/var/lib/nginx:/sbin/nologin
aaa5:x:1001:1001::/home/aaa5:/bin/bash

#模拟取出正确的身份证号码(18位 且最后一位有可能是X)
[root@xian /server/scripts]# cat sfz.txt 
lx 123465755343443675
lx 436456D546567F4656
lx A45476797898065776
lx 40980348594503485X
lx 3274543785674352X2
lx 93584375897589347X
lx 38947837543758342X
lx 348238493208423490
lx 23472364783657843C
[root@xian /server/scripts]# grep -Ew '[0-9X]{18}' sfz.txt 
lx 123465755343443675
lx 40980348594503485X
lx 3274543785674352X2
lx 93584375897589347X
lx 38947837543758342X
lx 348238493208423490
[root@xian /server/scripts]# grep -Ew '[0-9]{17}[0-9X]{1}' sfz.txt 
lx 123465755343443675
lx 40980348594503485X
lx 93584375897589347X
lx 38947837543758342X
lx 348238493208423490

四、正则表达式之Sed文本替换实例

三剑客第二 擅长取行 、增删改查

1.sed命令选项

选项 作用
-n 取消默认输出
-i 真正的修改文件
-r 支持扩展正则
-e 允许多项编辑

2.sed命令参数

命令参数 作用
p 打印
d 删除
s 替换
g 全局
a 追加
i 插入
c 替换,在当前行替换
w 将匹配的内容写入指定文件中
i 忽略大小写

3.sed命令实例操作

#打印-p参数实例
[root@xian /server/scripts]# sed  -n '1p'  passwd
root:x:0:0:root:/root:/b!in/bash
[root@xian /server/scripts]# sed  -n '1,3p'  passwd
root:x:0:0:root:/root:/b!in/bash
bin:x:1$:1:bin:/bin:/sb@in/nologin
daemon:x:2:2:daemon:/%sbin:/sbin/nologin
[root@xian /server/scripts]# sed  -n '1p;3p'  passwd
root:x:0:0:root:/root:/b!in/bash
daemon:x:2:2:daemon:/%sbin:/sbin/nologin
[root@xian /server/scripts]# sed  -n '/root/p'  passwd
root:x:0:0:root:/root:/b!in/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@xian /server/scripts]# sed  -n '/root/p;/halt/p'  passwd
root:x:0:0:root:/root:/b!in/bash
halt:x:7:0:halt:/sbin:/sbin'/halt
operator:x:11:0:operator:/root:/sbin/nologin
[root@xian /server/scripts]# sed  -nr '/root|nginx/p'  passwd
root:x:0:0:root:/root:/b!in/bash
operator:x:11:0:operator:/root:/sbin/nologin
nginx:x:998:996:Nginx web server:/var/lib/nginx:/sbin/nologin

#删除-d参数实例
[root@xian /server/scripts]# sed  '1,23d' passwd

[root@xian /server/scripts]# sed  '1d;3d' passwd

[root@xian /server/scripts]# sed  '/aaa5/d' passwd

[root@xian /server/scripts]# sed  '/aaa5|nginx/d' passwd

#替换-s g i 参数实例
g 是全局 (如果不加g,则只替换每一行的第一个符合的数据)
[root@xian /server/scripts]# cat passwd
root:x:0:0:root:/root:/b!in/bash
[root@xian /server/scripts]# sed 's#root#lixian#' passwd
lixian:x:0:0:root:/root:/b!in/bash
[root@xian /server/scripts]# sed 's#root#lixian#g' passwd
lixian:x:0:0:lixian:/lixian:/b!in/bash
#多行替换
[root@xian /server/scripts]# sed '1,5s#root#lixian#g' passwd

#替换忽略大小写
[root@xian /server/scripts]# sed '1,5s#root#lixian#gi' passwd

#追加-a参数实例
#追加到第一行下面
[root@xian /server/scripts]# sed '1awohenshuai' passwd
root:x:0:0:root:/root:/b!in/bash
wohenshuai
bin:x:1$:1:bin:/bin:/sb@in/nologin
#追加多行到第一行下面
[root@xian /server/scripts]# sed '1awohen\nshuai' passwd
root:x:0:0:root:/root:/b!in/bash
wohen
shuai
bin:x:1$:1:bin:/bin:/sb@in/nologin
#插入多行到第一行前面
[root@xian /server/scripts]# sed '1iwohen\nshuai' passwd
wohen
shuai
root:x:0:0:root:/root:/b!in/bash
bin:x:1$:1:bin:/bin:/sb@in/nologin
#替换的方式追加到第一行行首
[root@xian /server/scripts]# sed '1s#^#lixian\n#g' passwd
lixian
root:x:0:0:root:/root:/b!in/bash
bin:x:1$:1:bin:/bin:/sb@in/nologin

#行替换-c参数实例 (相当于把第一行删了 然后写入一行内容进去替换这一行)
[root@xian /server/scripts]# cat passwd
root:x:0:0:root:/root:/b!in/bash
bin:x:1$:1:bin:/bin:/sb@in/nologin
[root@xian /server/scripts]# sed '1c lixian' passwd
lixian
bin:x:1$:1:bin:/bin:/sb@in/nologin
#匹配bin开头的行删除并替换内容
[root@xian /server/scripts]# sed '/^bin/c lixian' passwd
root:x:0:0:root:/root:/b!in/bash
lixian

#写入到一个文件-w参数实例
#过滤nginx和ntp的行写入到文件中
[root@xian /server/scripts]# sed -nr '/nginx|ntp/wlixian.txt' passwd
[root@xian /server/scripts]# cat lixian.txt 
ntp:x:38:38::/etc/ntp:/sbin/nologin
nginx:x:998:996:Nginx web server:/var/lib/nginx:/sbin/nologin
#第十行到第十五行内容写入到一个文件内
[root@xian /server/scripts]# sed -nr '10,15wlixian.log' passwd
[root@xian /server/scripts]# cat lixian.log 
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
#删除没有空格和tab键的空行
[root@xian /server/scripts]# sed '/^$/d' default.conf 
server {
    listen       80;
    server_name  localhost;
    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;
    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
}

#删除有空格和tab键的空行
[root@xian /server/scripts]# sed '/^[ \t]*$/d' default.conf
[root@xian /server/scripts]# sed '/^\s*$/d' default.conf

#删除带有注释行、空格行、tab行
[root@xian /server/scripts]# sed -r '/^[ \t]*($|#)/d' default.conf 
server {
    listen       80;
    server_name  localhost;
}

#给所有文件内容加注释
[root@xian /server/scripts]# sed  's/^/#/g' default.conf 
#server {
#    listen       80;
#    server_name  localhost;
#
#    # deny access to .htaccess files, if Apache's document root
#    # concurs with nginx's one
#}
#

#将多余的#号及空格、tab符去掉
[root@xian /server/scripts]# cat default.conf 
##server {
#     listen       80;
##    #server_name  localhost;
#  #
##    #charset koi8-r;
#   #  access_log  /var/log/nginx/host.access.log  main;
##
##    # deny access to .htaccess files, if Apache's document root
#     concurs with nginx's one
##}
[root@xian /server/scripts]# sed 's/^[ \t#]*/#/g' default.conf 
#server {
#listen       80;
#server_name  localhost;
#
#charset koi8-r;
#access_log  /var/log/nginx/host.access.log  main;
#
#deny access to .htaccess files, if Apache's document root
#concurs with nginx's one
#}

五、正则表达式之Awk文本取列实例

1. Awk基本介绍

awk是一种编程语言 gawk 对于底层的操作系统的文本及数据处理

2.Awk处理数据的方式

1. 读入文件,按行进行读取,从第一行到最后一行

2. 寻找匹配的条件的行,在行上进行操作

3. 如果此行没有满足条件的,会丢弃,没有指定条件的,会把当前行内容全部打印出来

3.Awk的语法

awk [option] ‘command’ files

4.处理模式

行处理前      行处理中     行处理后
BEGIN{}        {}  		 END{}

[root@xian /server/scripts]# awk 'BEGIN{print 9-1}{print $2}END{print "命令结束"}'  /etc/hosts
8
localhost
localhost
命令结束

5.Awk的工作原理

[root@xian /server/scripts]# awk -F: '{print $1,$2}'  passwd
1. awk将文件中的每一行作为输入,并将每一行处理的时候放入到特定的模式空间中,将每一行的数据赋值给内部变量$0, 以换行符结束

2. awk开始进行字段分解,每个字段存储在自己的内部变量中, 变量从$1开始 

3. awk默认字段分割是由内部变量FS来指定的,可以使用-F修订,默认的分割符为空白字符

4. awk行处理时使用print来打印分割后的字段 

5. awk在打印之后会给不同的字段之间加上空格作为输出分隔符,这个分割符是由书写的逗号进行映射,逗号被映射到内部变量输出分隔符OFS,默认输出分隔符就是空格

6. awk输出之后,将从文件中读取下一行内容,并将其存储到$0变量中,覆盖原来的内容,然后接着进行循环处理,直到文件行处理结束

6.Awk内部变量

#使用默认输入分隔符   默认分隔符为空白字符
[root@xian /server/scripts]# awk '{print $2}'  /etc/hosts
localhost
localhost

#指定分隔符
[root@xian /server/scripts]# awk -F: '{print $1}'  passwd 
root
bin
daemon
adm
lp
sync
[root@xian /server/scripts]# awk 'BEGIN{FS=":"}{print $1}'  passwd
root
bin
daemon
adm
lp
sync

#指定多个分隔符 
[root@xian /server/scripts]# ip a s eth0 | awk -F '[ /]*' 'NR==3{print $3}'
10.0.0.99
[root@xian /server/scripts]# ip a s eth0 | awk  'BEGIN{FS="[ /]*"}NR==3{print $3}'
10.0.0.99

#输出分隔符  OFS (输出分隔符默认为空格  使用逗号进行映射 )
[root@xian /server/scripts]# awk 'BEGIN{FS=":";OFS="@"}{print $1,$2}'  passwd
root@x
bin@x
daemon@x
adm@x
lp@x

# -v  使用内部变量  定义awk内部变量
[root@xian /server/scripts]# awk  -F: -vOFS="$"  '{print $1,$2}'  passwd 
root$x
bin$x
daemon$x
adm$x
lp$x
[root@xian /server/scripts]# awk  -vFS=":" -vOFS="$"  '{print $1,$2}'  passwd
root$x
bin$x
daemon$x
adm$x
lp$x

#最后一列  NF  显示最后一列的编号,显示此行有多少列   $NF 打印最后一列
[root@xian /server/scripts]# awk -F:  '{print NF,$NF}' passwd
7 /bin/bash
7 /sbin/nologin
7 /sbin/nologin
7 /sbin/nologin
7 /sbin/nologin
[root@xian /server/scripts]# awk -F:  '{print $(NF-1)}' passwd 
/root
/bin
/sbin
/var/adm
/var/spool/lpd

#行号 FNR  记录每个文件的行号或者编号 
[root@xian /server/scripts]# awk '{print NR,$0}' passwd   /etc/hosts
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
[root@xian /server/scripts]# awk '{print FNR,$0}' passwd   /etc/hosts
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

#格式化输出
#使用Awk的一种方式,自定义输出
[root@xian /server/scripts]# date | awk '{print "今年是:"$NF"\t月份为:"$2}'
今年是:2020	月份为:May


7.Awk模式动作

# 正则表达式
[root@xian /server/scripts]# awk '/^root/'  passwd 
root:x:0:0:root:/root:/bin/bash
[root@xian /server/scripts]# awk '/t$/'  passwd 
halt:x:7:0:halt:/sbin:/sbin/halt
[root@xian /server/scripts]# awk '!/n$/'  passwd
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
halt:x:7:0:halt:/sbin:/sbin/halt
[root@xian /server/scripts]# awk '$0 ~/^root/' passwd 
root:x:0:0:root:/root:/bin/bash
[root@xian /server/scripts]# awk -F: '$3 ~/0/' passwd 
root:x:0:0:root:/root:/bin/bash

#比较表达式
两个数值或者字符进行比较,只有条件为真时,才会执行指定的动作 

关系运算符 
<
>
<=
>=
==
!=
[root@xian /server/scripts]# awk -F: '$3==0' passwd 
root:x:0:0:root:/root:/bin/bash
[root@xian /server/scripts]# awk -F: '$3==0{print $1}' passwd 
root
[root@xian /server/scripts]# awk -F: '$3<6{print $1,$3}' passwd 
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
[root@xian /server/scripts]# awk -F: '$3>6{print $1,$3}' passwd 
halt 7
mail 8
operator 11
[root@xian /server/scripts]# awk -F: '$3>=6{print $1,$3}' passwd 
shutdown 6
halt 7
mail 8
operator 11
[root@xian /server/scripts]# awk -F: '$1 == "root" ' passwd
root:x:0:0:root:/root:/bin/bash
[root@xian /server/scripts]# awk -F: '$1 == "root" && $3 == 0 ' passwd
root:x:0:0:root:/root:/bin/bash
[root@xian /server/scripts]# awk -F: '$1 == "root" ||  $3 == 1 ' passwd 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[root@xian /server/scripts]# awk -F: '$1 != "root"' passwd
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
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@xian /server/scripts]# awk -F: '$1 ~/^r/'  passwd 
root:x:0:0:root:/root:/bin/bash
[root@xian /server/scripts]# awk -F: '$3 ~/^1/'  passwd
bin:x:1:1:bin:/bin:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@xian /server/scripts]# awk -F: '$3 !~/1$/'  passwd 
root:x:0:0:root:/root:/bin/bash
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
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
[root@xian /server/scripts]# df  | awk '/\/$/'
/dev/sda3       18863104 2572044  16291060  14% /

#条件表达式
[root@xian /server/scripts]# awk -F: '{if($3==0){print "管理员"$1}else{print "普通用户"$1}}' passwd
管理员root
普通用户bin
普通用户daemon
普通用户adm
普通用户lp
普通用户sync
普通用户shutdown
普通用户halt
普通用户mail
普通用户operator
[root@xian /server/scripts]# awk -F: '{if($3==0){print "管理员"$1}}' passwd 
管理员root
[root@xian /server/scripts]# awk -F: '$3 == 0{print "管理员"$1}' passwd 
管理员root

#运算表达式
[root@xian /server/scripts]# awk 'BEGIN{print 1 + 1}'
2
[root@xian /server/scripts]# awk -F: '$3 + 10 >15' passwd 
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@xian /server/scripts]# awk -F: '/mail/{print $3}' passwd 
8
[root@xian /server/scripts]# awk -F: '/mail/{print $3 * 10 }' passwd
80


#逻辑操作符  复合模式
&&  ||  !
[root@xian /server/scripts]# awk -F: '$1 == "root" && $3 == 0{print "管理员为:"$1}' passwd
管理员为:root
[root@xian /server/scripts]# awk -F: '$1 == "root" || $3 == 1{print $1}' passwd
root
bin
[root@xian /server/scripts]# awk -F: '$1 !~/^r/' passwd 
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
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@xian /server/scripts]# awk 'NR==1' passwd 
root:x:0:0:root:/root:/bin/bash
[root@xian /server/scripts]# awk '/root/' passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@xian /server/scripts]# awk '!/root/' passwd 
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
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

解释下面命令的作用和含义

# awk '/west/' datafile    打印所有关于west的行
# awk '/^north/' datafile    打印所有以north开头的行
# awk '$3 ~ /^north/' datafile    #打印第三列中以north开头的行
# awk '/^(no|so)/' datafile   #打印以no和so开头的行
# awk '{print $3,$2}' datafile  #打印第三列和第二列,并且以空格分隔
# awk '{print $3 $2}' datafile  #打印第三列和第二列
# awk '{print $0}' datafile    #打印所有的行
# awk '{print "Number of fields: "NF}' datafile   #打印文件的列数
# awk '/northeast/{print $3,$2}' datafile    #打印所有northeast的行,输出第三列和第二列
# awk '/^[ns]/{print $1}' datafile   #打印以ns开头的行,并且输出第一列
# awk '$5 ~ /\. [7-9]+/' datafile   #打印第五列7到9的数字
# awk '$2 !~ /E/{print $1,$2}' datafile  打印第二列不匹配关于E的行的第1列和第2列
# awk '$3 ~ /^Joel/{print $3 "is a nice boy."}' datafile    #打印第三列以Joel开头输出第三列
# awk '$8 ~ /[0-9][0-9]$/{print $8}' datafile    #打印第八列两位数字结尾输出第八列
# awk '$4 ~ /Chin$/{print "The price is $" $8 "."}' datafile   #打印第四列以China结尾的第八列
# awk '/Tj/{print $0}' datafile   #打印所有Tj的行
# awk -F: '{print "Number of fields: "NF}' /etc/passwd    # #以:为分隔符输出文件的列数
# awk -F"[ :]" '{print NF}' /etc/passwd     #以:和空格为分隔符输出文件的列数

8.Awk的条件判断

if 表达式 动作

if 表达式 动作 else 动作

if 表达式 动作 else if 表达式 动作 else 动作

#打印当前系统中管理员用户
[root@xian /server/scripts]# awk -F: '{if($3==0){print $1"为系统管理员用户"}}'  passwd
root为系统管理员用户
[root@xian /server/scripts]# awk -F: '{if($3>0){i++}}END{print "系统用户的数量为:"i}' /etc/passwd
系统用户的数量为:30
[root@xian /server/scripts]# awk -F: '{if($3>0 && $3<1000){i++}}END{print "系统用户的数量为:"i}' /etc/passwd
系统用户的数量为:23
[root@xian /server/scripts]# awk -F: '{if($3>=1000){i++}}END{print "普通用户的数量为:"i}' /etc/passwd
普通用户的数量为:7
[root@xian /server/scripts]# awk -F: '{if($3==0){a++}else if($3>0 && $3<1000){b++}else{c++}}END{print "管理员 数量为:"a,"系统用户数量为:"b,"普通用户数量为:"c}'  /etc/passwd
管理员数量为:1 系统用户数量为:23 普通用户数量为:7



9.Awk的循环语句

#for循环
#1. 打印1-5的数字
[root@xian /server/scripts]# awk 'BEGIN{for (i=1;i<=5;i++){print i}}'
1
2
3
4
5

#创建10个用户
[root@xian /server/scripts]# awk 'BEGIN{for (i=1;i<=10;i++){print "useradd lx"i}}' | bash

#创建10个不同日期的文件
[root@xian /server/scripts]# awk 'BEGIN{for (i=1;i<=10;i++){print "date -s 2020/05/"i" &>/dev/null && touch /tmp/file-"i".txt"}}'  | bash


#while  循环
#打印1-10的数字
[root@xian /server/scripts]# awk 'BEGIN{a=1;while(a<=5){print a;a++}}'
1
2
3
4
5

#创建10个用户
[root@xian /server/scripts]# awk 'BEGIN{a=1;while(a<=10){print "useradd qls"a;a++}}' | bash

#创建10个不同日期的文件
[root@xian /server/scripts]# awk 'BEGIN{a=1;while(a<=10){print "date -s 2020/05/"a" &>/dev/null && touch /tmp/file-"a".txt";a++}}'  | bash


10.Awk数组

i++ #统计次数 i[$1]++

i+= #求和 i+=$1

#1.统计/etc/passwd文件中每一种shell的数量
[root@xian /server/scripts]# awk -F: '{Shells[$NF]++}END{for(i in Shells){print "Shell: "i,"Count: "Shells[i]}}'  /etc/passwd
Shell: /bin/sync Count: 1
Shell: /bin/bash Count: 11
Shell: /sbin/nologin Count: 21
Shell: /sbin/halt Count: 1
Shell: /sbin/shutdown Count: 1

#2. 统计tcp11中状态
[root@xian /server/scripts]# netstat  -ant | awk   'NR>2{State[$NF]++}END{for(i in State){print "State: "i,"Count: "State[i]}}'
State: LISTEN Count: 6
State: ESTABLISHED Count: 1

#3. 计算1-100之间的和 
[root@xian /server/scripts]# seq 100| awk '{Sum+=$1}END{print Sum}'
5050

#4. 统计日志中的PV量  一条日志就等于一个PV
[root@xian /server/scripts]# wc -l access.log
37593 access.log
[root@xian /server/scripts]# awk '{i++}END{print i}' access.log
37593
[root@xian /server/scripts]# awk '{PV[$1]++}END{for (i in PV) {Sum+=PV[i]}{print Sum}}'  access.log
37593

#5. 统计访问最多的10个IP地址
[root@xian /server/scripts]# awk '{Ips[$1]++}END{for (i in Ips)print "IP地址为: "i,"访问次数为: "Ips[i]}'  access.log |sort -rnk4 | head | column -t
IP地址为:  139.226.172.217  访问次数为:  16033
IP地址为:  47.102.42.79     访问次数为:  1041
IP地址为:  180.95.238.82    访问次数为:  994
IP地址为:  113.140.249.33   访问次数为:  727
IP地址为:  223.166.74.124   访问次数为:  647
IP地址为:  112.87.125.55    访问次数为:  525
IP地址为:  182.138.163.167  访问次数为:  429
IP地址为:  112.87.125.53    访问次数为:  373
IP地址为:  223.166.74.198   访问次数为:  352
IP地址为:  182.138.158.169  访问次数为:  308

#6. 统计访问次数大于500次的IP地址
[root@xian /server/scripts]# awk '{Ips[$1]++}END{for (i in Ips){if(Ips[i]>500){print "访问次数大于100次的IP地 址为: "i,"访问次数为: "Ips[i]}}}'  access.log |sort -rnk4 | column -t
访问次数大于100次的IP地址为:  139.226.172.217  访问次数为:  16033
访问次数大于100次的IP地址为:  47.102.42.79     访问次数为:  1041
访问次数大于100次的IP地址为:  180.95.238.82    访问次数为:  994
访问次数大于100次的IP地址为:  113.140.249.33   访问次数为:  727
访问次数大于100次的IP地址为:  223.166.74.124   访问次数为:  647
访问次数大于100次的IP地址为:  112.87.125.55    访问次数为:  525
[root@xian /server/scripts]# awk  '{Ips[$1]++}END{for (i in Ips){if (Ips[i]>500){print i,Ips[i]}}}' access.log  | sort -rnk2 | column -t
139.226.172.217  16033
47.102.42.79     1041
180.95.238.82    994
113.140.249.33   727
223.166.74.124   647
112.87.125.55    525

#7. 统计访问最多的10个URL页面  $11 
[root@xian /server/scripts]#  awk '{Url[$11]++}END{for(i in Url){if(Url[i]>100) {print i,Url[i]}}}' access.log |sort -rnk2|head 
"-" 16062
"https://www.increase93.com/" 7284
"https://www.increase93.com/?p=116" 2000
"https://www.increase93.com/?p=193" 1805
"https://www.increase93.com/?cat=5&paged=3" 886
"https://www.increase93.com/?p=292" 847
"https://www.increase93.com/wp-content/themes/QQ2.8/style.css?ver=4.1" 714
"https://www.increase93.com/?p=131" 522
"https://www.increase93.com/?p=458" 391
"https://www.increase93.com/wp-content/themes/QQ2.8/css/font-awesome.css" 326

#8. 统计每种状态码的数量  
[root@xian /server/scripts]# awk '{state[$9]++}END{for(i in state){print i,state[i]}}' access.log |sort -rnk2
200 26302
302 6108
404 2507
401 1084
304 986
499 185
206 149
400 111
150 99
301 33
504 11
405 8
SP1 4
Vezir.04 3
413 1
408 1
403 1

#9. 统计所有IP请求访问响应数据总大小   $10  
[root@xian /server/scripts]# awk '{Sum+=$10}END{print Sum}' access.log
1308567366

#10. 统计每个IP地址访问的状态码的数量
[root@xian /server/scripts]# awk '{Ips_State["IP: "$1" State: "$9]++}END{for (i in Ips_State){print i,"Count: "Ips_State[i]}}' access.log  | grep 139.226.172.217
IP: 139.226.172.217 State: 200 Count: 14731
IP: 139.226.172.217 State: 206 Count: 88
IP: 139.226.172.217 State: 404 Count: 193
IP: 139.226.172.217 State: 499 Count: 99
IP: 139.226.172.217 State: 302 Count: 108
IP: 139.226.172.217 State: 304 Count: 805
IP: 139.226.172.217 State: 504 Count: 9

#11. 统计每个IP地址的服务端响应的总字节大小及次数
[root@xian /server/scripts]# awk '{Ips[$1]++;Sum[$1]+=$10}END{for (i in Ips){print "IP: "i,"Count: "Ips[i],"Size: "Sum[i]}}' access.log  | sort -rnk4 | head | column -t
IP:  139.226.172.217  Count:  16033  Size:  749869585
IP:  47.102.42.79     Count:  1041   Size:  16462
IP:  180.95.238.82    Count:  994    Size:  154136
IP:  113.140.249.33   Count:  727    Size:  105270
IP:  223.166.74.124   Count:  647    Size:  93670
IP:  112.87.125.55    Count:  525    Size:  15640394
IP:  182.138.163.167  Count:  429    Size:  62205
IP:  112.87.125.53    Count:  373    Size:  10792077
IP:  223.166.74.198   Count:  352    Size:  61217
IP:  182.138.158.169  Count:  308    Size:  44660

#12. 统计每个IP地址访问URL页面的服务端响应的总字节大小及次数
[root@xian /server/scripts]# awk '(sum+=$10){print sum}' access.log |tail -n1 
1308567366

#13. 统计状态码为200的次数 
[root@xian /server/scripts]# awk '{state[$9]++}END{for(i in state){print i,state[i]}}' access.log |sort -rnk2|grep 200
200 26302


本站博主 , 版权所有丨如未注明 , 均为原创
转载请注明原文链接:Shell脚本编程学习——Shell正则表达式应用【显哥出品,必为精品】
喜欢 (0)

您必须 登录 才能发表评论!