shell正则表达式(grep、sed、awk)

一、grep

1、什么是grep,它有什么作用?

Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。

2、grep 的格式和参数的使用

grep [options]
[options]主要参数:
-c:只输出匹配行的计数。
-i:不区分大 小写(只适用于单字符)。
-h:查询多文件时不显示文件名。
-l:查询多文件时只输出包含匹配字符的文件名。
-n:显示匹配行及 行号。
-s:不显示不存在或无匹配文本的错误信息。
-v:显示不包含匹配文本的所有行。
pattern正则表达式主要参数:
\: 忽略正则表达式中特殊字符的原有含义。
^:匹配正则表达式的开始行。
$: 匹配正则表达式的结束行。
\<:从匹配正则表达 式的行开始。
>:到匹配正则表达式的行结束。
[ ]:单个字符,如[A]即A符合要求 。
[ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求 。
?:所有的单个字符。
* :有字符,长度可以为0。

3、示例

grep格式
参数
grep    root  passwd       模糊匹配(贪婪模式只要有)
grep    ^root  passwd      以root开头的行
grep    root$  passwd      以root结尾的行
grep -i root  passwd       忽略大小写
grep -E root  passwd       -E扩展正则表达式

在passwd文件中只要有root都查找出来
这里写图片描述
查找以root开头的
这里写图片描述
查找以root结尾的
这里写图片描述
查找只要有root的,忽略大小写
这里写图片描述
查找除passwd文件中只要有root或者ROOT的
这里写图片描述
查找passwd文件中以root开头并且以root结尾的
egerp 相当于grep -E
^root 匹配以root开头的行
root$ 匹配以root结尾的行
这里写图片描述
显示passwd文件中匹配字符root的行(忽略大小写),并且不以root开头或结尾的行
-v:显示不包含匹配文本的所有行。
- i :不区别大小写
注意下面两种不同表达的方式,表达的意思是相同的
这里写图片描述
这里写图片描述

grep root passwd              匹配root字符
grep -E "root\>" passwd       匹配root字符的行
grep -E "\<root\>" passwd     匹配root字符的行
grep -E "^\<root\>" passwd    匹配以root开头的行
grep -E "\<root\>$" passwd    匹配以root结尾的行
grep -E -i "\<root\>" passwd  匹配所有root字符(-i表示忽略大小写)

例子
1、匹配root字符的行
这里写图片描述
2第一个显示是以匹配字符开头的行
第二个显示以匹配字符结尾的行
这里写图片描述
3、匹配只要有字符root的行(忽略大小写)
这里写图片描述

grep中的正则表达式
grep -E "r.." file     匹配r后面只要大于等于有两位字符的
grep -E "r..\>" file    匹配r后面只有两位的
grep -E "\<r..\>" file  匹配r后面仅有两位的,前面没有后面也没有
grep -E "..t" file     匹配t前面只要大于等于有两位字符的
grep -E "\<..t" file    匹配t前面只有两位字符的

例子
1、匹配r后面至少有字符的
这里写图片描述
2、匹配r后面只有四个字符就结束的
这里写图片描述
3、匹配以t结尾的并且前面至少有四个字符的
这里写图片描述
4、匹配t前面只有四个字符的
这里写图片描述
5、匹配以t结尾并且 t前面只有四个字符的
这里写图片描述
6、匹配以r开头并且后面只有三个字符的
这里写图片描述

grep中字符的匹配次数设定
*    字符出现0-任意次
\?   字符出现0-1次
\{n\} 字符出现n次

示例

[root@localhost mnt]# grep -E 'ro*t' file
#匹配rt之间有0到任意个o字符的
#-E 代表匹配字符的
#* 代表0到任意个字符
[root@localhost mnt]# grep -E 'ro?t' file
#匹配rt之间有0-1个o字符的
#? 代表0-1
[root@localhost mnt]# grep -E 'ro{1,}t' file
#匹配rt之间至少有一个o字符的
#{1,} 代表大于等于1
[root@localhost mnt]# grep -E 'root' file
#查找file文件中以root为一个整体字符的
[root@localhost mnt]# grep -E '(root){2,}' file
#查找以root为1个字符并且连续出现两次以上的
#{2,}大于等于2
[root@localhost mnt]# grep -E "\<r+t" file
#匹配以r开头并且以rt为以整体的出现的
#+代表将两个分隔开的字符连接成一个整体的字符
[root@localhost mnt]# grep -E "\<r+t\>" file
#代表以r开头,以t结尾的并且rt至少出现一个
[root@localhost mnt]# grep -E "(rt)+" file
#以rt为一个整体字符至少出现一次的

例子
1、匹配rt之间有0到任意个o字符的
这里写图片描述
2、匹配rt之间有0到1个o字符的
这里写图片描述
3、匹配rt之间至少有一个o字符的
这里写图片描述
4、查找file文件中以root为一个整体字符的
这里写图片描述
5、查找以root为1个字符并且连续出现两次以上的
这里写图片描述
6、匹配以r开头并且以rt为以整体的出现的
这里写图片描述
7、代表以r开头,以t结尾的并且rt至少出现一个
这里写图片描述
8、以rt为一个整体字符至少出现一次的
这里写图片描述

例用grep 相关规则表达式完成下面的题目

1、显示含有主机ip的行

[root@localhost mnt]# ifconfig eth0
#查看ip信息
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.25.254.118  netmask 255.255.255.0  broadcast 172.25.254.255
        inet6 fe80::5054:ff:fe00:3c0a  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:00:3c:0a  txqueuelen 1000  (Ethernet)
        RX packets 4429  bytes 482501 (471.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2963  bytes 322014 (314.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@localhost mnt]# ifconfig eth0 | grep inet
#过滤含有inet的行
        inet 172.25.254.118  netmask 255.255.255.0  broadcast 172.25.254.255
        inet6 fe80::5054:ff:fe00:3c0a  prefixlen 64  scopeid 0x20<link>
[root@localhost mnt]# ifconfig eth0 | grep -E  "inet\>"
#过滤inet结尾的行
        inet 172.25.254.118  netmask 255.255.255.0  broadcast 172.25.254.25

2、查找出这台主机允许登陆的用户

编辑show_loginuser.sh这个文件
这里写图片描述

#########################
# author: lucy          #
# Version:     
# Mail:        
# Date:        2018-06-20
# Description: 
#              
#########################

#! /bin/bash
SHELL=$(echo `grep -v nologin /etc/shells` | sed 's/ /|/g')
#查找出/etc/shell中不含有nologin的行,并且将全文中的空格替换为|
grep -E "$SHELL" /etc/passwd |  cut -d : -f 1
#在/etc/passwd文件中查找没有nologin的并且将全文中替换的空格替换为分隔符号|(此时显示的信息是这台主机允许登陆的用户的相关信息),然后通过管道进行传输,再进行以:为分隔符,截取第一列信息(只显示用户)

执行脚本后,显示允许登陆的用户,下图显示只有root和student用户才被允许
这里写图片描述
当我们在指定的文件中建立用户user1时候,执行脚本后多了一个user1用户
这里写图片描述

二、sed

1、什么是sed

sed是一种很好的行编辑器,以行为单位,可以对数据进行删除,新增,替换,选取等操作。
sed:用来操作纯 ASCII 码的文本
sed处理原理:处理时 , 把当前处理的行存储在临时缓冲区中 , 称为“模式空间” (pattern space) 可以指定仅仅处理哪些行,sed 符合模式条件的处理不符合条件的不予处理处理完成之后把缓冲区的内容送往屏幕接着处理下一行 , 这样不断重复 , 直到文件末尾 。

2、sed的处理模式

sed 对字符的处理的模式:
p     显示
d     删除
a     添加
c     替换
w     写入
i     插入

(1)p操作模式:显示

[root@localhost mnt]# sed  -n  '/^#/p'  fstab
#显示fstab文件中以#开头的行

这里写图片描述

[root@localhost mnt]# sed  -n  '/^#/!p'  fstab
#显示除了以#号为开头的行

这里写图片描述

[root@localhost mnt]# sed  -n  '/0$/p'  fstab
#显示以0结尾的行

这里写图片描述

[root@localhost mnt]# sed -n '3p'  fstab
#显示fstab文件中的第三行信息

这里写图片描述

[root@localhost mnt]# cat -n fstab | sed -n '2,6p'
#显示fstab2到6行内容

这里写图片描述

[root@localhost mnt]# cat -n fstab | sed -n -e '2p' -e '6p'
#显示fstab中第二行和第6行内容
[root@localhost mnt]# cat -n fstab | sed -n  '2p;6p'
#显示fstab中的第二行和第6行内容 

这里写图片描述
这里写图片描述

[root@localhost mnt]# cat -n fstab  | sed -ne '2!p;6!p' | uniq -d
#除了第二行和第六行其余行重复显示并且uniq -d只显示重复的行

这里写图片描述
这里写图片描述

[root@localhost mnt]# cat -n fstab  | sed -ne '2!p;6!p' | uniq -u
#显示不重复的行

这里写图片描述

(2)d模式操作: 删除

sed '/UUID/d'    删掉UUID的行
sed '/^UUID/d'   删掉以UUID开头的行
sed '/UUID$/d'   删掉以UUID结尾的行
sed '1,4d' fstab 删掉1-4
[root@localhost mnt]# sed '/UUID/d' fstab
#删除UUID这一行

这里写图片描述

[root@localhost mnt]# sed '/^UUID/d' fstab
#删除以UUID开头的行
#
# /etc/fstab
# Created by anaconda on Wed May  7 01:22:57 2014
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/vg0/vo /home   ext4    defaults    0 0
[root@localhost mnt]# sed '/info$/d' fstab
#删除以info结尾的行

#
# /etc/fstab
# Created by anaconda on Wed May  7 01:22:57 2014
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
#
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1
/dev/vg0/vo /home   ext4    defaults    0 0
[root@localhost mnt]# sed '1,3d' fstab
#删除fstab文件的1到3行
# Created by anaconda on Wed May  7 01:22:57 2014
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1
/dev/vg0/vo /home   ext4    defaults    0 0

(3)a模式操作:添加

[root@localhost mnt]# sed '/^UUID/a hello\n world' fstab
#在以UUID开头的行添加hello和world并换行
#
# /etc/fstab
# Created by anaconda on Wed May  7 01:22:57 2014
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1
hello
 world
/dev/vg0/vo /home   ext4    defaults    0 0

(4).i模式操作:保存到原文件

[root@localhost mnt]# sed '/^UUID/i hello'   fstab
#在以UUID开头的行中插入hello
#
# /etc/fstab
# Created by anaconda on Wed May  7 01:22:57 2014
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
hello #由
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1
/dev/vg0/vo /home   ext4    defaults    0 0

(4)w模式操作:写入

[root@localhost mnt]# sed -n  '/^UUID/w westos' fstab
#将以UUID开头的这一行内容写入到westos文件中

这里写图片描述
这里写图片描述

[root@localhost mnt]# sed  '1r hello' fstab
#fstab文件的第一行中写入hello文件中的内容

这里写图片描述

[root@localhost mnt]# sed  '$r hello' fstab
#在fstab文件的最后一行写入文件的内容

这里写图片描述

(6)c模式:替换

[root@localhost mnt]# sed   '/^UUID/c hello' fstab
#将fstab文件中以UUID为开头的这一行修改为hello文件的内容

这里写图片描述

(7)sed其他用法

sed -n '/^UUID/='  fstab     显示fstab文件的UUID行号
sed -n -e '/^UUID/p' -e '/^UUID/='  fstab   
把fstab文件的UUID行打印出来并显示行号
sed 'G'  fstab     给每行后面加行空格
sed '$!G' fstab    给每行后面加行空格,除了最后以行
sed '='  fstab  | sed 'N;s/\n/ /'   给每一行前面加入行号
sed -n '$p' fstab                   显示最后一行

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

脚本练习

利用脚本的形式建立用户


[root@localhost mnt]# vim userfile
[root@localhost mnt]# vim passfile
[root@localhost mnt]# cat userfile 
user1
user2
user3
[root@localhost mnt]# cat passfile 
user1123
user2123
user3123
[root@localhost mnt]# vim user_test.sh
#!/bin/bash
MAX_LINE=`wc -l $1| cut -d " " -f 1`
for LINE_NUM in `seq 1 $MAX_LINE`
do
     USERNAME=`sed -n "${LINE_NUM}p" $1`
     PASSWORD=`sed -n "${LINE_NUM}p" $2`
     useradd $USERNAME
     echo $PASSWORD| passwd --stdin $USERNAME
done

编写脚本使得自动安装阿帕奇并使用指定端口:

[root@localhost mnt]# vim apache_port.sh 
#编辑自动安装apache并且指定apache端口的文件
#! /bin/bash
yum install httpd.x86_64 -y #安装httpd服务
sed -i "/^Listen/cListen $1" /etc/httpd/conf/httpd.conf; #找出以Listen开头的行,并进行修改端口
echo  ; #插入空行
echo the  listen is changed; #提示端口已经改变
sed -ne '42p' /etc/httpd/conf/httpd.conf #显示httpd服务配置文件的第42行信息
systemctl restart httpd #重新启动httpd服务
~   
[root@localhost mnt]# sh apache_port.sh 
#执行脚本

例子
这里写图片描述
这里写图片描述

这里写图片描述
这里写图片描述
这里写图片描述

三、awk

一个 awk脚本通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块3部分组成,这三个部分是可选的。任意一个部分都可以不出现在脚本中,脚本通常是被单引号或双引号中;
例如:

(1) BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。
(2)pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。
(3)END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。

[root@localhost mnt]# awk -F : 'BEGIN{print "NAME"}{print $1}' passwd
#以:为分隔符,处理前打印 NAME ,打印第1列
[root@localhost mnt]# awk -F : 'BEGIN{print "NAME"}{print $1}END{print NR}' passwd
#以:为分隔符,处理前打印 NAME ,打印第1列,处理后打印行数(NF列)
[root@localhost mnt]# awk -F : '/bash$/{print $7}' passwd/bin/bash
#以:为分隔符,打印以bash结尾行的第7列
[root@localhost mnt]# awk -F : '/bash$/' passwd
#以:为分隔符,打印以bash结尾行
[root@localhost mnt]# awk -F : 'NR== 3' passwd
#以:为分隔符,打印第3行
[root@localhost mnt]# awk -F : 'BEGIN{print "NAME"}NR<=3&&NR>=2{print $1}' passwd
#以:为分隔符,处理前打印 NAME ,打印2-3行的第1个字符
[root@localhost mnt]# awk '!/^[a-d]/{print}' passwd
#显示不以a到d字母开头的行

这里写图片描述
这里写图片描述

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述


[root@localhost mnt]# awk -F ":" 'BEGIN{N=0}$6!~/^\/home/&&/bash$/{N++}END{print N}'  /etc/passwd
#显示能登陆系统的在home下用户由几个
1
[root@localhost mnt]# awk -F ":" '$6!~/^\/home/&&/bash$/{print $1}' /etc/passwd
#显示能登陆系统的在home下用户
root
[root@localhost mnt]# awk -F ":" 'BEGIN{N=0}/bash$/{N++}END{print N}'  /etc/passwd
#显示能登陆系统的用户有几个
2

脚本练习

显示主机的ip

只显示主机的ip
[root@localhost mnt]# awk -F = '/IPADDR0/{print $2}' /etc/sysconfig/network-scripts/ifcfg-eth0 
172.25.254.218
[root@localhost mnt]# ifconfig eth0 | awk -F " " '/inet\ /{print $2}'
172.25.254.218

例子
这里写图片描述
这里写图片描述
这里写图片描述

打印文件的行数

[root@localhost mnt]# awk  "BEGIN{N=0}{N++}END{print N}"  /etc/passwd
#显示/etc/passwd文件的行数
42
[root@localhost mnt]# awk 'END{ print NR }' /etc/passwd
#显示/etc/passwd文件的行数\
42

这里写图片描述
这里写图片描述
这里写图片描述

猜你喜欢

转载自blog.csdn.net/dhjibk/article/details/80719256