码迷,mamicode.com
首页 > 其他好文 > 详细

[8-27]正则表达式、扩展表达式以及相关实战

时间:2015-08-31 15:29:13      阅读:287      评论:0      收藏:0      [点我收藏+]

标签:正则   gre   扩展正则   bre   

本文旨在复习正则表达式,扩展正则表达式,对基本概念、基本用法等作记录


知识储备


  • 正则表达式:是文本搜索工具,根据用户指定的“PATTERN模式”去逐行匹配目标文本,打印匹配到的

    • 模式: 由正则表达式的元字符及文本字符,所编写的过滤条件

    • 元字符:字符不标识其字面意义,用于表示通配或控制功能;

    • 逐行: 请注意:正则处理单位是“行”,匹配时去匹配行,输出时输出行

  • 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:],特殊法本质上是预先定义好的字符集合,按照规定引用即可
在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.有一个特殊用法 .* 表示任意长度的任意字符

位置锚定

行为单位
^        行首锚定, 简而言之就是 紧跟的字符为 行为首的行
$        行尾锚定,简而言之就是 前一个字符为 行尾的行
^$       特殊用法,表示空行
请注 空行是该行啥都没有,只有一个$行尾结束符。而不是空格,看下面这个实验
技术分享
词为单位 --> 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,但是不需要\来特殊申明了
*
?        匹配前一个字符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


作业实战


3、显示/etc/passwd文件中以bash结尾的行

答:这道题没啥好说的,最基本的 bash+行尾锚定

技术分享


4、显示/etc/passwd文件中的两位数或三位数

答:这道题除了如下写法,还可以使用\<限定词锚定

技术分享


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]是一个整体,你懂得

技术分享



本文出自 “蓝色仓库” 博客,请务必保留此出处http://bluebox.blog.51cto.com/8852456/1690081

[8-27]正则表达式、扩展表达式以及相关实战

标签:正则   gre   扩展正则   bre   

原文地址:http://bluebox.blog.51cto.com/8852456/1690081

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!