03.编程学习--正则表达式(入门一)

作者: 北静王 | 来源:发表于2016-05-01 23:40 被阅读634次

    文:郑元春

    人生苦短,我用Python!

    0x01:什么是正则表达式

    In theoretical computer science and formal language theory, a regular expression (sometimes called a rational expression)[1][2] is a sequence of characters that define a search pattern, mainly for use in pattern matching with strings, or string matching, i.e. "find and replace"-like operations. The concept arose in the 1950s, when the American mathematician Stephen Kleene formalized the description of a regular language, and came into common use with the Unix text processing utilities ed, an editor, and grep, a filter.
    --《Wiki Regular expression
    中文简述:在理论计算科学领域和形式化语言理论中,regular expression(有时候也叫做rational expression)是一种定义了搜索模式的特征序列,主要是用于字符串的模式匹配,或是字符的匹配。

    熟悉Linux的同学肯定在shell中就用过各种各样的正则表达式,基本上每种语言,像是C++,Java,JavaScript和Python等都是支持正则表达式的应用。有的时候书写起来可能会有细微的差别,并且对正则符号的支持程度也不一样。

    由于近来要做些NLP之类的处理,所以就学习了下Python中的正则表达式。学会使用正则表达式真的会极大的提高你的开发效率,但是正则表达式学习起来是有一定的门槛的,因为里面会牵扯到一定的模式抽象能力,相比于其他的问题来说有点难度。不过,作为一个程序员,被人称为情商加到智商上的生物,我们不应该就是勇往直前么。

    看过一些大牛写的正则表达式,真的是既简洁又很优雅。并且很神奇的能够处理那些看似复杂的文本解析任务。我的个人理解是正则表达式就是一组高效的规则的模式集合

    某个程序员的理解是:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

    0x02:Python中的正则表达式

    正则表达式并不是Python的一部分,效率上可能不如str自带的方法,但功能十分强大。

    1.字符类

    • 1.1一般字符(就是简单的字符)

    就是没有任何正则元字符的正常字符串

    比如匹配abcababc 将会找到两个 abc,需要注意的是匹配的时候是从前向后挨个匹配的,像 ababa只能找到一个aba

    • 1.2 \

    将正则元字符(当成正则式中的关键字)转义成正常的字符。

    import re  #记得载入正则模块
    #case 1 没有使用转义
    reStr='a.c'
    targetStr="abc a.c a\\c"
    re.findall(reStr,targetStr)
    #结果是:
    >>>['abc', 'a.c', 'a\\\\c']
    

    解释:因为你这里没有使用转义,所以a.c中的.就是一个正则元字符(.的作用会在下面讲解),所以上面的代码会选出多个符合条件的子字符串。

    #case 2 使用转义
    reStr='a\\.c'
    re.findall(reStr,targetStr)
    #结果是:
    >>>['a.c',]
    ```
    *解释*:这样就只把`a.c`给提取出来了。
    
    - 1.3`.`
    
    代替任何单个字符(换行除外)
    ```
    reStr="a.c"
    targetStr="abc a.c abb"
    re.findall(reStr,targetStr)
    
    >>>['abc','a.c']
    ```
    
    -  1.4`[]`
    
    对应的位置可以是字符集的任何一个字符。除了直接给出字符集,你还可以给出字符范围
    
    ```
    #case 1:直接列出字符集
    reStr="a[12bc]ef"
    targetStr="a1ef abef a12bcef"
    re.findall(reStr,targetStr)
    >>>['a1ef', 'abef']
    
    #case 2:使用范围
    reStr="a[1-5a-d]ef"
    targetStr="a3ef a6ef acef a1eef"
    re.findall(reStr,targetStr)
    >>>['a3ef', 'acef']
    
    #当然[]中你还可以添加其他的规则
    ```
    
    #### 2.预定义字符类(可以写在[]中的)
    
    - 2.1`\\d`和`\\D`
    数字:`\\d`=`[0-9]`
    非数字:`\\D`=`[^\\d]`=`[^0-9]`
    
    ```
    targetStr="123abc"
    
    #case 1:数字
    reStr="\\d"
    re.findall(reStr,targetStr)
    >>>['1','2','3']
    
    #case 2:非数字
    reStr="\\D"
    re.findall(reStr,targetStr)
    >>>['a','b','c']
    
    #case 3:非数字
    reStr="[^0-9]"
    re.findall(reStr,targetStr)
    >>>['a','b','c']
    ```
    *注意:不推荐使用`[^\\d]` 或者是`[^\\D]`的表示方式,如果你忘记了[],结果就会是错误的*
    
    - 2.2`\\s`和`\\S`
    空白字符:`\\s`=[<space>\\t\\r\\n\\f\\v]
    非空白字符:`\\S`=[^\\s]
    
    ```
    #case 1:空白字符
    reStr="\\s"
    targetStr="a\\nb a\\tb"
    re.findall(reStr,targetStr)
    >>>['\\n', ' ', '\\t']
    
    #case 2:非空白字符
    reStr="a\\Sc"
    targetStr="abc a.c"
    re.findall(reStr,targetStr)
    >>>['abc', 'a.c']
    ```
    
    空白字符是包括所有的空格字符,有的文本编辑器会使用<space>替代`tab` 键,此时需要注意。`\\S`和`.`的区别是`.`包括了`\\S`.
    
    - 2.3`\\w`和`\\W`
    单词字符:`\\w`=[A-Za-z0-9_]
    非单词字符:`\\W`=[^\\w]
    
    ```
    #case 1:能够组成单词的字符
    reStr="a\\wc"
    targetStr="abca2caBca c"
    re.findall(reStr,targetStr)
    >>>['abc', 'a2c', 'aBc']
    ```
    
    #### 3.数量词(用字字符或是`()`之后)
    
    - 3.1`*`
    匹配请一个字符0次或者是无数次
    
    ```
    reStr="a*c" #匹配 'c' 'ac' 'aac' 'a...c'
    targetStr="ac aac abc aaac"
    re.findall(reStr,targetStr)
    >>>['ac', 'aac', 'c', 'aaac']
    ```
    *注意abc中c是符合的*
    
    - 3.2`+`
    匹配前一个字符1次或者是无数次
    
    ```
    reStr="a+c" #匹配 'ac' 'aac' 'a...c'
    targetStr="ac aac abc aaac"
    re.findall(reStr,targetStr)
    >>>['ac', 'aac', 'aaac']
    ```
    
    - 3.3`?`
    匹配前一个字符0次或者是1次
    
    ```
    reStr="a?c" #匹配 'c' 'ac'
    targetStr="ac aac abc aaac"
    re.findall(reStr,targetStr)
    >>>['ac', 'ac', 'c','ac']
    ```
    
    - 3.4`{m}`
    匹配前一个字符m次
    
    ```
    reStr="a{2}c" #只匹配 "aac"
    targetStr="ac aac abc aaac"
    re.findall(reStr,targetStr)
    >>>['aac','aac']
    ```
    
    - 3.5`{m,n}`
    匹配前一个字符从m次到n次
    当只有m的时候表示m-无数次
    当只有n的时候表示0-n次
    
    ```
    reStr="a{1,2}c" #只匹配 'ac' 'aac'
    targetStr="ac aac abc aaac"
    re.findall(reStr,targetStr)
    >>>['ac', 'aac', 'aac']
    ```
    
    #### 4.边界匹配
    
    - 4.1`^`
    匹配字符串开头
    在多行模式中匹配每一行的开头
    
    ```
    #case 1:没有开启多行模式
    reStr="^abc"
    targetStr="abc\\nabcd\\nbabc"
    re.findall(reStr,targetStr)
    >>>['abc']
    
    #case 2:开启多行模式
    r=re.compile(reStr,re.M)
    r.findall(targetStr)
    >>>['abc', 'abc']
    ```
    
    - 4.2`$`
    匹配字符串末尾
    在多行模式中匹配每一行的末尾
    
    ```
    reStr="-a$"
    targetStr="abc-a\\n123-a\\n-a\\na\\n-b"
    r=re.compile(reStr,re.M)
    r.findall(targetStr)
    >>>['-a', '-a', '-a']
    ```
    
    - 4.3`\\A`
    仅匹配字符串开头
    
    ```
    reStr="\\Aabc"
    targetStr="abcabc"
    re.findall(reStr,targetStr)
    >>>['abc']
    ```
    这个只会匹配字符串的开头,只要是开头没有的话那就是没匹配上
    
    - 4.4`\\Z`
    仅匹配字符串结尾
    
    ```
    reStr="abc\\Z"
    targetStr="aaabc"
    re.findall(reStr,targetStr)
    >>['abd']
    ```
    
    - 4.5`\\b`
    匹配那些在单词字符和非单词字符之间的“位置”(之所以称这个为位置,是因为这不是一个字符,比如`a-`中是在`a`和`-`之间的位置),姑且认为他是一个特殊字符吧!
    
    >注意在Python中`\\b`代表着是是退格键的意思,如果要使用正则表达式的话需要转义以下,就是使用`\\\\b`,当然,你也可以使用`r'\\b'`使用Python的raw型的字符串(注意前面的`r`).其实就是内部自动做了转义。
    
    ```
    #case 1: 单纯的`\\\\b`匹配问题
    reStr="\\\\b"
    targetStr="a a a"
    re.findall(reStr,targetStr)
    >>>['', '', '', '', '', '']
    ```
    
    >为什么这里会是6个“位置”呢?注意的实际情况是这样的:中间有两个非单词字符(空格),每个空格跟左右的单词字符有4个“位置”,再加上整个字符串的首位2个位置,所有有6个位置。是不是更加的深入了解了“位置”的意思了呢。
    
    ```
    #case 2:字符和"\\\\b"的搭配使用
    targetStr="ao-ao-ao"
    reStr=r"ao\\b"  #注意这里的`r`
    re.findall(reStr,targetStr)
    >>>['ao','ao','ao']
    ```
    >这里就是查找`ao`后面跟个位置的模式,是不是很好理解了已经。
    
    - 4.6`\\B`
    这个也和上一个一样,是一个特殊的位置。匹配的是单词字符和单词字符之间的位置。
    
    ```
    #case 1: 单纯的"\\\\B"
    reStr="\\\\B"
    targetStr="a _a"
    re.findall(reStr,targetStr)
    >>>['']
    ```
    *解释*:这里的结果就是在下划线和`a`之间的这个位置。
    
    ```
    #case 2:和其他模式搭配
    reStr=r"a\\B"
    targetStr="aa-aaa"
    re.findall(reStr,targetStr)
    >>>['a', 'a', 'a']
    ```
    *解释*:这里模式想找的是字符`a`并且a后面还有其他的单词字符跟着。如果换成target="aa-a_a"的话,那么结果就是只有两个`a`被找到了。
    
    >写在最后:今天是劳动节了,已经在昨天爬了香山,所以决定未来的三天假期就不出门了。早上起了很晚,慢悠悠的处理了手头上的一点工作,然后一天完成了这点文章,终于对正则表达式有了点深刻的认识。祝愿大家节日快乐,劳动人民最光荣!下一篇讲解剩余的正则表达式的知识。
    
    ### 参考
    
    - [正则表达式-wiki](http://www.wikiwand.com/en/Regular_expression)
    - [正则表达式-在线测试](http://tool.oschina.net/regex/)
    - [Python中的正则表达式](http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html)
    - [re - Regular expression operations](https://docs.python.org/2/library/re.html)
    - [Python中正则表达式模块--`re`的使用](http://www.cnblogs.com/sevenyuan/archive/2010/12/06/1898075.html)

    相关文章

      网友评论

      本文标题:03.编程学习--正则表达式(入门一)

      本文链接:https://www.haomeiwen.com/subject/sfrfrttx.html