练习正则表达式

    正则表达式可以通过元字符(规则)来匹配查找相关的的字符集合。他与通配符是有区别的。而且相关的使用工具对正则表示的元字符的是有区别的。

    首先我们先来了解下常用的元字符及含义(并不是所有的元字符)

字符匹配      
         .(点)一个任意字符,回车符换行符除外
         [ ]匹配所包含的任意一个字符
         [^xyz]负值字符集合。匹配未包含的任意字符。        
         [a-z]字符范围。匹配指定范围内的任意字符。        
             注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围;        
             如果出字符组的开头,则只能表示连字符本身.        
         [^a-z]^表示取反;匹配不在指定范围内的任意一个字符。        
         [:space:] 一个空白字符        
         [:punct:] 一个(所有)标点符号        
         [:lower:] 一个小写字母 [a-z]  不能写成[z-a]        
         [:upper:] 一个大写字母 [A-Z]        
         [:digit:]  一个数字    [0-9]        
         [:alnum:] 一个数字和字母 [A-Z0-9a-z]        
         [:alpha:]  一个大小写字母 [a-zA-Z]
位置锚定
        ^ 匹配输入字符串的开始位置。行首  写在左侧
        $匹配输入字符串的结束位置。写在行尾
        \b匹配一个单词边界,
        \B匹配非单词边界。
        \< \>匹配词(word)的开始(\<)和结束(\>)。
重叠次数
        *匹配前面的子表达式、字符零次或多次(大于等于0次)。
        +匹配前面的子表达式一次或多次(大于等于1次)
        ?匹配前面的子表达式零次或一次。(基本表达式需要转意 \)
        {n}前面字符匹配n次。 (基本表达式需要转意 \)
        {n,}至少匹配n次,至多不管啊   (基本表达式需要转意 \)
        {n,m}其中n<=m。最少匹配n次且最多匹配m次。  (基本表达式需要转意 \ )
特殊功能
        ( ) 将 \( 和 \) 之间的表达式定义为“组”(group),并将匹配到的字符保存到一个临时区域
       (一个正则表达式中最多可以保存9个),可以用 \1 到\9 的符号来引用。分组中的模式匹配到的内容,
        可由正则表达式引擎记忆在内存中,之后可被引用有编号:自左而后的左括号,以及与其匹配右括号
        (基本表达式需要转意 \)
        \n引用第n个括号所匹配到的内容,而非模式本身
        |将两个匹配条件进行逻辑“或”(Or)运算。扩展正则表达式
        \转义符号,把后面的字符特殊的转为普通,普通的转为特殊

   这上面的这些字符没有别的办法就是记住和理解,其实就是规则文字游戏并不是一开始接触时候的时候所认认为的那么难。重要的是先对单个元字符去实验下然后再去组合。综合而言正则表达式就是计算机所能识别的并被人类所能操作的一种语言,他有很多组合方式来实现你所想要的功能。

    使用正则表达式之前首先肯定是有需求或者说是目标,然后分析组合匹配规则。在这里我感觉还是使用扩展正则表达式的好,无需纠结。

    首先准备一串字符,我放在了/tmp/ceshi

    130 120 200 450 12 24 70 140 8000 30
    30 120 200 450 12 24 170 140 80
    78 30 1800 200 450 12 24 170 40 80
    30 1800 200 450 120 24 170 40 70 70 70
    389 30 1800 200 450 120 24 1000 40 70
    30 30 1800 200 450 120 24 1000 40 70
    130120 200 450122470140800030
    30120200450122417014080
    7830180020045012241704080
    3018002004501202417040707070
    3893018002004501202410004070
    303018002004501202410004070

 匹配下以30开头中间必须含有70的字符串:

    1、单个匹配以30为开头:需要做行首锚定^30

    2、单个含有70: 70 

    3、组合匹配需要注意中间30和70之间是可以经过任意字符的.*

    ^30.*70

    [root@zhuzw-centos6 tmp]# cat ceshi | grep -E "^30.*70"
    30 120 200 450 12 24 170 140 80
    30 1800 200 450 120 24 170 40 70 70 70
    30 30 1800 200 450 120 24 1000 40 70
    30120200450122417014080
    3018002004501202417040707070
    303018002004501202410004070

   

 匹配下以30开头中间必须包含1800以70结尾的字符串:

    还是同样的步骤分析几个重要的点

    1、30开头:^30

    2、中间必须包含1800: 1800前后都有可能存在字符 .*1800.*

    3、以70结尾:70$

    ^30.*1800.*70$

    [root@zhuzw-centos6 tmp]# cat ceshi | grep -E "^30.*1800.*70$"
    30 1800 200 450 120 24 170 40 70 70 70
    30 30 1800 200 450 120 24 1000 40 70
    3018002004501202417040707070
    303018002004501202410004070
    要求30后面需要跟一个空白字符呢?
    要求30后面需要跟上1或者3呢?   
    ^30[ ].*1800.*70$
    ^30[1|3].*1800.*70$

 再来试几个简单的实例

 1、要求70 至少出现2次最多出现3次

    我们需要用到{n,m}其中n<=m。最少匹配n次且最多匹配m次。

    70{2,3}是这样吗?我们来试试

    [root@zhuzw-centos6 tmp]# cat ceshi | grep -E "70{2,3}"
    [root@zhuzw-centos6 tmp]# echo $?
    1

    执行错误了为什么呢?仔细看看元字符你会发现它们基本上都是针对单个字符.

    70{2,3}实际表示的意思应该是700|7000.

    那么我们如何匹配多个字符呢?这就用到了().

    [root@zhuzw-centos6 tmp]# cat ceshi | grep -E "(70){2,3}"
    3018002004501202417040707070

    这里需要注意下\n 匹配的是()里面的匹配处来的内容而不是里面的子表达式

    n从外圈开始计算,最外圈的为1

    [root@zhuzw-centos6 tmp]# cat ceshi | grep -E "(6(7(\<200\>)))*.*\3?.*[ ]70$"
    30 1800 200 450 120 24 170 40 70 70 70
    389 30 1800 200 450 120 24 1000 40 70
    30 30 1800 200 450 120 24 1000 40 70
    [root@zhuzw-centos6 tmp]# A400=200
    [root@zhuzw-centos6 tmp]# cat ceshi | grep -E "(6(7(\<`echo A400`\>)))*.*\3?.*[ ]70$"
    30 1800 200 450 120 24 170 40 70 70 70
    389 30 1800 200 450 120 24 1000 40 70
    30 30 1800 200 450 120 24 1000 40 70

    2、+和?这两个元字符其实用法跟{n,m}是一样的

    +可以写成{1,}至少出现1次,m不赋值表示无限制,但是不许符合n的要求。

    ?可以写成{0,1}

    对于 \B  \b \< \>呢你可以把上面字符中被空白字符隔开的一组数字看成是一个单词。

    \B200\B  \b200\b \<200\> 的区别通过下面的匹配输出就能对比出来了。

    [root@zhuzw-centos6 tmp]# cat ceshi | grep -E "\B200\B"
    30120200450122417014080
    7830180020045012241704080
    3018002004501202417040707070
    3893018002004501202410004070
    303018002004501202410004070
    [root@zhuzw-centos6 tmp]# cat ceshi | grep -E "\b200\b"
    130 120 200 450 12 24 70 140 8000 30
    30 120 200 450 12 24 170 140 80
    78 30 1800 200 450 12 24 170 40 80
    30 1800 200 450 120 24 170 40 70 70 70
    389 30 1800 200 450 120 24 1000 40 70
    30 30 1800 200 450 120 24 1000 40 70
    130120 200 450122470140800030
    [root@zhuzw-centos6 tmp]# cat ceshi | grep -E "\<200\>"
    130 120 200 450 12 24 70 140 8000 30
    30 120 200 450 12 24 170 140 80
    78 30 1800 200 450 12 24 170 40 80
    30 1800 200 450 120 24 170 40 70 70 70
    389 30 1800 200 450 120 24 1000 40 70
    30 30 1800 200 450 120 24 1000 40 70
    130120 200 450122470140800030

最后呢我们来匹配下一个邮箱地址

邮箱的格式 zhuzw_1203@126.com

这是126的邮箱名字规则:6~18个字符,可使用字母、数字、下划线,需以字母开头

grep -E "^[[:alpha:]]([a-z]|[A-Z]|[0-9]|[_]){5,17}@([[:alnum:]]+[\.])+[[:alnum:]]+$"
"[[:alpha:]]([a-z]|[A-Z]|[0-9]|[_]){5,17}@([[:alnum:]]+[\.])+[[:alnum:]]+"

字母开头[[:alnum:]]

可使用字母、数字、下划线 :([a-z]|[A-Z]|[0-9]|[_])

6~18个字符:{5,17}注意因为前面已经有开头的字母占一位了

@:@ 

邮箱后缀格式126.com :  ([[:alnum:]]+[\.])+[[:alnum:]]+

    英文大小写数字字符至少出现一次,转义.这个符号;把这两个字表达式作为一个组至少出现一次;最后匹配一个英文大小写数字字符至少出现一次。分组的原因是可能会有126.com.cn  126.163.com.cn 这种格式的出现。

    好了写到这里正则表达式的笔记和分享暂告一段落。最后呢其实还是大家先去分析下我们的最终目标然后结合语法去写;目标明确才好去实现。

原创文章,作者:东郭先生,如若转载,请注明出处:http://www.178linux.com/3213

(0)
东郭先生东郭先生
上一篇 2015-04-15
下一篇 2015-04-15

相关推荐

  • shell脚本基础练习2

    1.编写一个脚本/root/bin/createuser.sh,脚本的执行语法必须是:createuser.sh -username -m password,选项与参数间可支持多空格,但不能顺序颠倒。当未指定正确的选项或参数时,以错误输出方式提示“createuser.sh -u username -m password ”后退出脚本。用…

    2017-08-12
  • Linux文本处理工具

    知识框架图 学习笔记 查看文本 查看文本内容 cat -A:显示控制符 -E:显示行结束符$ -n:打印行号,显示空行 -b:打印行号,空行不编号 -s:压缩连续空白行 tac:反向查看文件内容 rev:文本每行倒序显示 分页查看 more less 查看文件头尾内容 head -c:前n个字节 -n:前n行 tail -c -n -f:跟踪显示文件变化,常…

    2018-03-17
  • 马哥教育网络班22期第五周课程练习1

    1、cat /etc/passwd  | egrep "^root|^fedora|^user1"| cut -d":" -f1,7  2、egrep -o  "[^[:space:]]+\(\)" /etc/rc.d/init.d/functions   3…

    Linux干货 2016-09-15
  • shell脚本(一)

     本周是来马哥教育的第四周,本周重点是shell脚本的编写,本篇博客也是以shell脚本的简述为主。 一.shell脚本的概念及意义     shell脚本是linux下的一种编程方式,百度百科给出这样的释义:脚本(shell script)是利用shell的功能所写的一个程序,这个程序是使用纯文本文件,将一…

    Linux干货 2017-08-05
  • systemd

    1、systemd (1)CentOS 7 使用systemd替换了SysV。Systemd目的是要取代一直在使用的init系统,兼容SysV和LSB的启动脚本,负责在系统启动或运行时,激活系统资源、服务器进程和其它进程。 (2)systemd的新特性: 系统引导是实现服务并行启动 按需启动守护进程 自动化管理各服务间的依赖关系 同时采用sockets式与D…

    Linux干货 2016-09-21
  • 逻辑卷的创建与移除

    一、弹性控制磁盘大小的lvm:     假如有这样一个场景,在初始安装linux系统时给 /home分区设置了一定大小,但是过了一段时间后,你发现初始分配的大小远不能满足公司的扩大,员工增加,需要分配的账号的磁盘空间也变大,这时你应该怎么办?是挂载一块更大的硬盘,将原来的小硬盘拆除掉吗?其实在linux中有lvm可动态增大文件系…

    Linux干货 2016-08-30