本文旨在复习正则表达式,扩展正则表达式,对基本概念、基本用法等作记录
知识储备
BRE与ERE:
BRE基本正则表达式,ERE扩展正则表达式
本质区别是[元字符的定义不一样罢了],常用参数是一致的
BRE与ERE可互相切换,grep命令中-E使用扩展正则,egrep中-G使用基本正则
FRE快速正则表达式
严格来说已经不是正则表达式了,单纯的字符文本匹配罢了
基本正则表达式BRE
Usage:
grep [OPTIONS] PATTERN [FILE...]
常用参数
-v:显示模式匹配不到的行,取反,这里是小写。大写是Version
-i:忽略字符大小写
-o:仅显示能够被模式匹配到的串本身,而不是行
-q:静默模式,无返回值,通过$?可以查看是否匹配到,0是匹配到,1是失败
-E:使用扩展的正则表达式
元字符:
字符匹配
. 匹配任意单个字符,请注意是单个
[] 匹配[]范围内的任意单个字符
[^] 匹配[]范围外地任意单个字符
请注意:[]表示字符集有2种常见的写法
枚举法:[A-Za-z]表示任意1个大小写字母,枚举法即将所有可能出现的字符写在[]里面,可以用","隔开,连续字符用“-”
特殊法:[:upper:]、[:alnum:]、[:alpha:],80);font-family:inherit;font-size:12.960000038147px;font-style:inherit;font-weight:inherit;background-color:inherit;">特殊法本质上是预先定义好的字符集合,按照规定引用即可
在ASNII编码中,[:alnum:]表示大小写和数字,而\w 还能够表示大小写字母、数字以及下划线 等价于[_A-Za-z0-9]
次数匹配
* 匹配前一个字符出现任意次,0次、1次、N次都可以
\? 匹配前一个字符出现0次或1次
\+ 匹配前一个字符出现1次或N次
\{m\} 精确匹配前一个字符出现了m次,一定是m次
\{m,n\} 匹配前一个字符至少m次,至多n次,相当于[m,n],有以下2种引申用法
\{m,\} 至少m次
\{0,n\} 至多n次
请注意:
1.次数匹配一定是针对前一个字符而言的,就是描述前一个字符出现了多少次
2.有一个特殊用法 .* 表示任意长度的任意字符
位置锚定
行为单位
^ 行首锚定,简而言之就是 紧跟的字符为 行为首的行
$ 行尾锚定,80);font-family:inherit;font-size:12.960000038147px;font-style:inherit;font-weight:inherit;background-color:inherit;">前一个字符为 行尾的行
^$ 特殊用法,表示空行
请注意: 空行是该行啥都没有,只有一个$行尾结束符。而不是空格,看下面这个实验
词为单位 --> Linux中单词的定义和英文单词不一样,标点符号作为单独单词,连续字母or数字组成算单词
\< 词首锚定
\> 词尾锚定
\b 锚定边缘,这玩意儿,既可以锚定词首,也可以锚定词尾,
请注意:
1.通常\b可以匹配边缘[词首、词尾],单并非总是等价的,因为正则默认工作在贪婪模式,有时候\b匹配的范围大于使用\<\>
2.建议写成\< \> 这样易读,且易于排错
从上面的元字符我们可以看出来一件事,总是在强调匹配单个字符,如果对于lancelancexy如何去描述,或者说如何去匹配连续出现的2次lance呢?
分组:
使用\(ABCDE\)将多个字符捆绑起来作为整体,对整体你可以附加字符匹配、次数匹配等等;
分组匹配的内容保存在内置的变量中,这些变量分别是\1,\2,\3 ...
\1:从左侧起,第一个左括号以及与之配对的右括号 中间的模式 所匹配到的内容
\2:从左侧起,第2个。。。。。你懂的
这就是后向引用:使用变量引用前面的分组括号中的模式所匹配到的
请注意:为什么使用\(\) 而不是()本身?
答:其实这是由于bash决定的,在bash中()有指定意义.而grep命令又是由bash解析然后提请给内核的,所以如果使用()那么bash就不能理解为分组的含义,这就需要使用\来告诉bash这个括号表示为分组的含义,这也很好地解释了上面的\{\} 呵呵
扩展正则表达式BRE
Usage:
egrep [OPTIONS] PATTERN [FILE...]
常用参数同基本正则表达式,参考前文
元字符:
字符匹配 ---> 同BRE
.
[]
[^]
次数匹配 ---> 同BRE,80);font-family:inherit;font-size:12.960000038147px;font-style:inherit;font-weight:inherit;background-color:inherit;">但是不需要\来特殊申明了
*
? 匹配前一个字符0次或1次
+ 匹配前一个字符1次或N次
{m} 精确匹配前一个字符m次
{m,n} 次数在范围[m,n]中
位置锚定 ---> 同BRE
^
$
\<
\>
\b
分组 ---> 分组不需要\了
()后向引用\1 \2 \3
请注意:特殊A|B 用法
匹配整个|左侧 或 右侧,
如C|cat 表示的含义是C或者cat
如果想表示Cat或者cat 请使用 (C|c)at
作业实战
答:这道题没啥好说的,最基本的 bash+行尾锚定
答:这道题除了如下写法,还可以使用\<限定词锚定
5、显示`netstat -tan`命令结果中以‘LISTEN’后跟0个、1个或者多个空白字符结尾的行
这道题没啥好说的,最后的*也可以用\{0,\}这种写法,不过要注意[:space:]外侧需要加括号,字符集均如此
6、添加用户bash、testbash、basher以及nologin用户(nologin用户的shell为/sbin/nologin);而后找
这道题很有趣,当初我想用cut先切割/etc/passwd把用户名提取出来,然后通过管道送给grep来处理;
但是遇到2个难点:首先管道送给grep是送给grep当参数用,而我需要的是当grep的模式用;其次即便管道成功,那么cut切割后是N列用户名,而我需要是一次送一个用户名,还可能需要使用xargs,限于水平没这么做。
有人说我的\<.*\>范围太广不准确,其实我觉得正是因为范围广才不会出现漏情况。为何呢?因为/etc/passwd这个文件本身就是有规范的,不合法的用户名一定是不存在的,那么我用.*大范围一定能匹配到合法情况 不是吗?
7、显示当前系统上root、centos或者user1用户的默认shell和UID (请事先创建这些用户,若不存在)
答:使用egrep的 | 匹配用户名 |请注意此时输出的是行!正则是以行为单位匹配和输出的 |cut切割显示
8、找出/etc/rc.d/init.d/functions文件中某单词(单词中间可以存在下划线)后面跟着一组小括号的行
这道题解法各有不同,关键是你是如何理解和定义单词这个概念的?紧跟一组小括号,这里需要对()进行转义,否则在egrep中会把()当做分组处理。下面是我的写法,我用的是云服务器,截图不是全屏。
9、使用echo输出一个路径,而后egrep找出其路径基名;进一步的使用egrep取出其目录名
答:
基名:觉得简单但是当路径名结尾有/的时候,输出结果会携带/但这是不需要的,最终使用cut切割来解决豁然开朗
但是这样写其实也是有问题的,因为[:alnum:]匹配有限,如果是下面的情况那么就失效了
所以很难完完全全地考虑到所有情况解决这个问题,这道题能解决关键在于大部分人命名还是比较正常的。
目录名:这道题没想到太好的办法,多次过滤实现的
10、找出ifconfig命令执行结果中1-255之间的数字
思想很重要,主要是对1-255分层表述,数字1-9,数字10-99,数字100-199,数字200-249,数字250-255
在最初写得时候,我没有在两侧加上(),出现了下面的错误结果,这是因为如果没有()那么会将1028015这类也匹配到,这是为什么呢?因为|是针对整个左侧和右侧而言的,不加()意味着\<[1-9]是一个整体,你懂得