grep## 标题
概念:
-
在进行程序设计的过程中,用户会不可避免地遇到处理某些文本的情况。有的时候,用户还需要查找符合某些比较复杂规则的字符串。对于这些情况,如果单纯依靠程序设计语言本身,则往往会使得用户通过复杂的代码来实现。但是,如果使用正则表达式,则会以非常简短的代码来完成
-
正则表达式是通过一些特殊字符的排列,用以查找、替换、删除一行或多行文字字符串,简单的说,正则表达式就是用在字符串的处理上面的一项表示式。由于正则表达式语法简练,功能强大,得到了许多程序设计语言的支持,包括Java、C++、Perl以及Shell等
基本正则表达式
- 基本正则表达式(Basic Regular Expression,BRE),又称为标准正则表达式,是最早制订的正则表达式规范,仅支持最基本的元字符集。基本正则表达式是POSIX规范制订的两种正则表达式语法标准之一,另外一种语法标准称为扩展正则表达式
常见元字符
元字符 | 说明 |
---|---|
^ | 以某个字符开头 |
$ | 以某个字符结尾 |
. | 匹配任意单字符 |
***** | 对前一项进行0次或者多次重复匹配 |
{m,n} | 将前一项字符重复m-n次,{m,},{,n},{m,n} |
[] | 对方括号内的单字符进行匹配 |
[^] | 不匹配方括号内的单字符 |
1 | 匹配以某个字符开头的行 |
() | 定义一个子表达式 |
词首【\<或\b】和词尾锚定【\>或者\b】 | 其后面的任意字符必须作为单词首部出现;其前面的任意字符必须作为单词尾部出现 |
\ | 转义字符,让一些特殊符号失效 |
POSIX字符类
- POSIX字符类是一个形如
[:...:]
的特殊元序列(meta sequence),他可以用于匹配特定的字符范围
正则表达式 | 描述 | 示例 |
---|---|---|
[:alnum:] | 匹配任意一个字母或数字字符 | [[:alnum:]]+ |
[:alpha:] | 匹配任意一个字母字符(包括大小写字母) | [[:alpha:]] |
[:blank:] | 空格与制表符(横向和纵向) | [[:blank:]]* |
[:digit:] | 匹配任意一个数字字符 | [[:digit:]]? |
[:lower:] | 匹配小写字母 | [[:lower:]] |
[:upper:] | 匹配大写字母 | ([[:upper:]]+)? |
[:punct:] | 匹配标点符号 | [[:punct:]] |
[:space:] | 匹配一个包括换行符、回车等在内的所有空白符 | [[:space:]]+ |
[:graph:] | 匹配任何一个可以看得见的且可以打印的字符 | [[:graph:]] |
[:xdigit:] | 任何一个十六进制数(即:0-9,a-f,A-F) | [[:xdigit:]]+ |
[:cntrl:] | 任何一个控制字符(ASCII字符集中的前32个字符) | [[:cntrl:]] |
[:print:] | 任何一个可以打印的字符 | [[:print:]] |
示例
- [ab] : 检索包含a或包含b的行信息,[ ] 中只能表示一个内容
# 检索包含d或者D的行信息
[root@server ~]# grep -n [dD] /etc/passwd
# 检索包含字母o的行信息
[root@server ~]# grep -n [oo] /etc/passwd
- [^ ] : 根据关键字检索后反向显示(反向着色)
# 检索不包含字母o的行信息
[root@server ~]# grep -n [^o] /etc/passwd
# 检索不以r开头且包含oot的行信息
[root@server ~]# grep -n [^r]oot /etc/passwd
- [-] : 表示范围,如:[0-9] [a-z] [A-Z] [a-zA-Z]
# 检索包含7-9的行信息
[root@server ~]# grep -n [7-9] /etc/passwd
# 检索包含大写字母的行信息
[root@server ~]# grep -n [A-Z] /etc/passwd
# 检索包含数字和字母的行信息
[root@server ~]# grep -n [0-9a-zA-Z] /root/anaconda-ks.cfg
# 上例改写
[root@server ~]# grep -n [[:alnum:]] /root/anaconda-ks.cfg
- ^行首与$行尾
# 检索root开头的行信息
[root@server ~]# grep -n ^root /etc/passwd
# 检索以#开头的行信息
[root@server ~]# grep -n "^#" /root/anaconda-ks.cfg
# 检索以数字结尾的行信息
[root@server ~]# grep -n "[0-9]$" /root/anaconda-ks.cfg
# 检索空白行
[root@server ~]# grep -n "^$" /root/anaconda-ks.cfg
# 注意
[root@server ~]# grep -n ^[root] /etc/passwd # 检索以r开头或o开头或t开头,独立对待
[root@server ~]# grep -n ^root /etc/passwd # 检索root开头,整体对待
[root@server ~]# grep -n [^root] /etc/passwd # 检索不包含r或o或t的,反向着色
# 注意:^[] 与 [^] 区别
- 点(.) 与星号(*)
# 检索以r开头t结尾中间只有2个字符的行信息
[root@server ~]# grep -n r..t /etc/passwd
# 检索至少包含1个w字母的行信息
[root@server ~]# grep -n ww* /etc/passwd
# 检索至少包含2个字母o的行信息
[root@server ~]# grep -n ooo* /etc/passwd
# 检索包含(.)的行信息
[root@server ~]# grep -n "\." /etc/passwd # 需要加双引号
扩展正则表达式
概念
- 扩展正则表达式(Extended Regular Expression,ERE)支持比基本正则表达式更多的元字符,但是扩展正则表达式对有些基本正则表达式所支持的元字符并不支持。前面介绍的元字符“^”、“$”、“.”、“*”、“[]”以及“[^]”这6个元字符在扩展正则表达式都得到了支持,并且其意义和用法都完全相同,不再重复介绍。接下来重点介绍一下在扩展正则表达式中新增加的一些元字符。
元字符 | 说明 |
---|---|
? | 将前一项字符进行0次或者1次的重复匹配 |
+ | 将前一项进行1次或者多次的重复匹配 |
(|) | 匹配|符号左边或者右边的字符 |
示例
# 显示/etc/passwd 中以bash结尾的行信息
[root@server ~]# grep -n "bash$" /etc/passwd
# 找出/etc/passwd中包含三位数或者四位数的行信息
[root@server ~]# grep -n "\<[0-9]\{3,4\}\>" /etc/passwd
# 上例改写
[root@server ~]# grep -n "\<[[:digit:]]\{3,4\}\>" /etc/passwd
# 检索/etc/grub2.cfg文件中,以至少一个空白字符开头,后面跟上非空白字符的行
[root@server ~]# grep -n "^[[:space:]]\+[^[:space:]]" /etc/grub2.cfg
# 分析
# ^[[:space:]] :表示以空白字符开头
# \+:grep不支持扩展正则的元字符,需要转义
# [^[:space:]]:不包含非空白字符
# grep可以使用-E参数启用扩展正则,命令改为:
[root@server ~]# grep -nE "^[[:space:]]+[^[:space:]]" /etc/grub2.cfg
# 也可以使用egrep,其支持扩展正则,命令改为
[root@server ~]# egrep -n "^[[:space:]]+[^[:space:]]" /etc/grub2.cfg
# 检索netstat -tan 命令的运行结果中,以“LISTEN”后跟上0个或多个空白字符结尾的行信息
[root@server ~]# netstat -tan | grep "LISTEN[[:space:]]*$"
# *$表示重复前面0次或多次,$为结尾
# 检索fdisk -l 命令结果中,包含以/dev/开头后跟上n的行信息
[root@server ~]# fdisk -l | grep "^/dev/n"
# 检索 ldd /usr/bin/cat 命令结果中的文件路径
[root@server ~]# ldd /usr/bin/cat | grep -oE "/[^[:space:]]+"
# -o:只显示检索命中的标红内容
# -E:启用扩展正则
# 检索/proc/meminfo文件中,所有以大写A或大写S开头的行信息
[root@server ~]# grep -n "^[AS]" /proc/meminfo
# 显示/etc/passwd文件中当root、sshd、chrony的相关信息
[root@server ~]# egrep -n "(root|sshd|chrony)" /etc/passwd
# 需要使用egrep,其支持扩展正则
# (|) 会对|左右两边的整体内容进行匹配
# echo输出一个绝对路径,使用egrep取出其基名
[root@server ~]# echo /etc/yum.repos.d/ | egrep -o [^/]+/?$
# 检索ifconfig命令结果的1-255之间的整数
[root@server ~]# ifconfig | egrep -o "\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>"