grep
用来处理正则表达式的主要命令是grep,grep的基本功能是在文本文件中搜索与指定的正则表达式匹配的文本,将其输出至标准输出
grep [options] regex [file...]
常用选项 | 描述 |
---|---|
-i | 忽略大小写 |
-v | 反向匹配,即输出和正则表达式不匹配 |
-c | 输出匹配数量 |
-l | 输出包含匹配项的文件名 |
-L | 输出不包含匹配项的文件名 |
-n | 在输出的文本行之前加上行号 |
-h | 在多文件搜索中禁止输出文件名 |
-E | grep -E <=> egrep,即适用ERE扩展型正则表达式的grep |
当我们只对包含指定字符串的文件感兴趣,那么-l选项是非常有用的;
如果我们对不包含指定字符串的文件感兴趣,-vl可以实现这一功能;
多文件搜索会在匹配的文本行之前加上它所属的文件名,如果对文件不感兴趣,可以使用-h选项
注意-E选项,
元字符和文本字符
所谓的元字符是指表示特定含义的字符,区别于文本字符,正则表达式分为 基本型正则表达式BRE和扩展性正则表达式ERE,它们的不同之处在于:识别的元字符是不同的
注意:
-
很多元字符对于shell本身也是有意义的,比如*在shell中就可以扩展成任意长度的字符,所以,当正则表达式出现在命令行的时候,一定要将其放入引号中
-
反斜线\,可以用来创建元序列,也可以用来转义成文本字符,听起来很矛盾,但是看使用场景
任意字符.
元字符点号".",它用来匹配任意一个字符
锚点^和$
脱字符^和美元符号$ 被视为锚点,分别代表行首和行尾
# ^和$称为锚点非常合适,因为它们就是单纯地表示位置
grep -h '^zip$' dirlist*.txt
特别的:’^$’ 表示空行
多选结构 |
正则表达式 ‘AAA|BBB’ 的意思是要么匹配 ‘AAA’ 要么匹配 ‘BBB’,多选结构 ‘|’ 是ERE的特性之一
注意:
- 适用多选结构的时候,记得正则表达式加上引号,前文也说过,很多元字符在shell中也具有特殊意义,比如 ‘|’ 在shell中意味着管道,为了防止shell的展开规则对正则表达式的影响,如果在命令行上书写正则表达式,需要加上引号
量词
ERE扩展型正则表达式支持指定匹配次数
? 匹配零次或一次
该量词表示:之前的元素是可选的,可以有,也可以没有,或者说出现零次或一次
注意:
- 是紧邻着’?'的前一个字符,如果你想表示一块都是可选的,可以使用圆括号把它们括起来,组成一部分。
* 匹配零次或多次
类似于 ‘?’ 区别在于,*能够匹配多次
+ 匹配一次或多次
类似于 ‘?’ 或 ‘*’ ,区别在于匹配的次数
示例:
# 匹配由大写字母开头,其之后不管有几个大写字母或小写字母或空格都能匹配,最后以'.'结尾
'^[[:upper:]][[:upper:][:lower:] ]*\.$'
# 开头就是一个或多个字母,其后可能有空格,这样的组合重复一次或多次
'([[:alpha:]]+ ?)+'
{} 指定匹配的次数
共有四种指定的方式
指定方式 | 含义 |
---|---|
{n} | 匹配n次 |
{n,m} | 至少匹配n次,至多m次 |
{n,} | 至少匹配n次,无上限 |
{,m} | 至少匹配0次,至多m次 |
方括号和字符类
可以使用方括号来匹配指定范围字符中的单个字符
# 匹配含有bzip或者gzip的行
grep -h '[bg]zip' dirlist*.txt
排除
如果方括号中的首个字符是脱字符^,相当于取反匹配,即匹配不含有脱字符后面字符的行
注意:
- 只有当脱字符^作为方括号表达式中的第一个字符的时候,才表示排除含义;否则它只是一个普通的字符
字符范围
方括号还可以使用连字符,表示一段范围的字符,比如[a-zA-Z]表示小写字母和大写字母,[0-3]表示数字0、1、2、3
POSIX字符类
POSIX是IEEE制定的一套规范UNIX工作方式的标准,包括程序的接口、shell以及标准类UNIX系统中的实用工具
ASCII码表中,大写字母+小写字母顺序排列的
ABC...Zabc...z
正常的词典序列是,大小写间隔排列的
aAbBcC...zZ
POSIX引入了语言环境的概念,能够调整特定区域所需要的字符集,查看系统的语言设置echo $LANG
,总之,正因为如此,后来兼容POSIX的应用会使用词典序列,这样,显然[a-z]或者[A-Z]就不再具有通用性
因此,建议在匹配字符范围的时候,尽可能使用POSIX的字符类
常用的字符类 | 描述 |
---|---|
[:alnum:] | 字母和数字 <=> [a-zA-Z0-9] |
[:word:] | 在[:alnum:]的基础上增加了下划线_ |
[:alpha:] | 字母 <=> [a-zA-Z] |
[:digit:] | 数字0-9 |
[:lower:] | 小写字母 |
[:upper:] | 大写字母 |
[:space:] | 空白字符 |
ps:相信你还记得,POSIX类同样适用于和通配符搭配,用于shell扩展
应用示例
grep -Ev '^\([0-9]{3}\) [0-9]{3}-[0-9]{4}$' phonelist.txt
分析:第一段 ^\([0-9]{3}\)
表示开头就是一个括号,里面三个数字,使用转义字符是将圆括号转义成普通字符;第二段 [0-9]{3}-[0-9]{4}$
表示三个数字和四个数字,中间是连字符连接,至此结尾;grep -Ev则是表示使用ERE扩展型正则表达式,v则是表示不符合正则表达式规则的文本行将被找出来
find . -regex '.*[^-_./0-9a-zA-Z]'
分析:find选项 -regex,即使用ERE扩展型正则表达式,.*
表示匹配零个或多个字符,方括号以开头,则表示排除以后的字符;整体则表达找出不含-_./0-9a-zA-Z
的路径
locate --regex `bin/(bz|gz|zip)`
分析:–regex表示采用ERE扩展型正则表达式,看点主要是后面利用多选结构,匹配含有bz 或 gz 或 zip的文件名
注意:如果是多选结构,最后一开始就加上括号,表示多选结构是一块的,要不然可能会有纰漏,比如^(bz|gz|zip)
和^bz|gz|zip
表达的是不一样的,前者表示可能是bz开头或者gz或zip,后者则一定是bz开头其后或者是gz或者是zip
less或者vim均支持正则表达式查找,输入/或者?就能够查找,但是vim只支持BER基本型正则表达式,很多ERE中支持的元字符,在BER中就是普通字符,这个时候需要利用转义字符,将普通字符转义成元字符