首页 > 代码库 > 正则表达式的基本用法

正则表达式的基本用法

Perl 有很多其它语言所没有的特性,这其中对正则表达式(regular expression)的强大支持是它最为突出的一个亮点。正则表达式使得 perl 在处理文本时具有非常强大的优势:快速,灵活而且很可靠,甚至可以说,强大文本处理能力,是 perl 在众多语言中最为闪耀的一个特点。 因此学习 perl 的过程,必然也是学习正则表达式的过程,这或许多少给 perl 的学习增加了些少的负担,但好在正则表达式并不是 perl 所独有的, 它是一门使用非常广泛的语言,在很多工具及其它编程语言中都有广泛的支持,比如:grep,awk,sed,vi 等。它是如此的常见,以致于编程人员在很多场合都无可避免的要与之打交道,因此掌握好正则表达的好处是非常明显的,好在它的语法也很简单,学习起来也不算太难。

在 Perl 或其它一些语言及工具中,正则表达式通常也会叫为“模式"(pattern),正则表达式本质上来说是一个字符串模板,用来确认某个字符串是否符合这个模板的格式,任何一个字符串,要么符合这个模板,要么不符合这个模板。具体到在Perl中,正则表达式是用"/"围起来的,比如:($string =~ /pattern/)。在这里我们暂且称 string 为匹配串,只有当 string 匹配了 ”pattern" 这个串时,这个表达式才是true,反之为false。如: "abc ef ffff" =~ /ef/ 为 true,"abc" =~ /ee/ 为 false。

当然上面的例子只是最简单的情形,如果正则表达式只能做这样单纯的纯字符匹配,那它就不可能这么强大。

正则表达式通过一类特殊的字符,我们称为元字符或通配符(meta character)来进行字符的模糊表示,它们在匹配的过程中代表特殊的含义。下面我们就进行简单的介绍。


(1) 点号(.),

它用来匹配任意一个单字符(\n 排除在外,后面我默认不再提这个例外)。

        所以: "twoon" =~ /tw.on/   为 true

                  “twvon" =~ /tw.on/   也为 true.

        点号在正则表达式中是有特殊含义的,有时我们可能也要匹配点号,这时就需要转义一下。

        "twoo.n" =~ /twoo\.n/    为true.

        正则表达中,所有其它的通配符也都可以用同样的方式进行转义,表示直接匹配通配符,去除它的特殊含义。

        你可以看到\也是一个通配符,如果要匹配它也是同样的道理。

        "two\\on" =~ /two\\on/ 为true.


(2) 星号(*) :

星号代表匹配它前面一个字符任意遍(0或任意次),它是一数量词(quantifier),必须跟在其它字符的后面,否则这个表达式不正确。

        如: ”twoon" =~ /two*n/      为true

              “twn"     =~ /two*n/     也为true.

               "twoon" =~ /*twoon/   表达式不正确,*必须跟在其它符号后面.

      同时星号也可以匹配点号(.),点号代表任意非回车字符,因此, (.*)就代表任意字符任意次。这是一个惯常的用法,如:   /twoon.*walks/    能匹配任意包含"twoon"在前,"walks“在后的字符串。所以(.*)也被称为:any old junk. 匹配任何东西。 


(3) 加号(+): 加号是一个与星号(*)类似的通配符,它也是数量词,表示匹配前面的字符一次或多次(至少一次).

       它与星号的差别就在这里,星号可以匹配0次,加号则必须一次以上。  

        如:"twoon" =~ /two+n/ 为true.

              "twn"    =~ /two+n/ 为false.


(4) 问号(?): 问号也是一个数量词,它代表匹配前一个字符0或1次。

        如: "twoon" =~ /twoo?n/ 为true

               "twoon” =~ /two?n/ 为false.

               "twn"   =~ /two?n/ 为true.


(5) 括号(()): 括号用来表示一个组合,前面我说数量词作用在前一个字符上,这个说法事实上不准确,应该说是作用在一个组合上,一个字符是一个组合,但多个字符也可以成为组合。括号就是用来表示一个组合,被括号括起来的就是一个组合。

        如: "twoon" =~ /tw(o)*n/ 为true.

              "twoon" =~ /tw(oo)*n/ 为true

             "twowon" =~ /t(wo)*n/ 为true.

              "twoon" =~ /t(wv)*oon/ 为false.

               “twoon" =~ /t(wo)+on/为true.

               "twon"   =~ /t(wo)+on/为false.

     括号里可以放置任何字符,也可以放置其它通配符,如  "aaabcc" =~ /(aa+b)?cc/


(6) 引用通配符:反斜杠加上数字是所谓引用通配符(back reference): \1 \2 \3 等,它的作用是引用前面的某个括号元组,如:  

          "twoonwo" =~ /t(wo)on\1/   为true

    乍看起来,似乎作用不明显,如上例,我们完全可以不用\1,而写成这样: /t(wo)on(wo)/

    在上面的例子里,这个质疑是可以理解的。但有时,我们的括号元组可能这样写的:  (we...) 因为点号代表任意字符,如果我们后面要作用这个元组,不用引用通配符, 我们根本无法引用,具体看例子:    

          ”weabceeweabc" =~ /(we...)ee\1/  为 true。

          “weabceeweabc" =~ /(we...)ee(we...)/ 为 true

          ”weabceewecdf" =~ /(we...)ee(we...)/  也为 true.

    从第2,3个例子,我们可以看区别。\1 表示的是与前一个元组完全一样的匹配。而 \1,\2,\3等,则分别表示,从左往右数第几个元组。

          “abcdef def abc" =~ /(...)(...) \2\1/ 为 true.

    在 perl 中,引用通配符中支持从1~9,写法上很活,你既可直接\1 \2 ...\9这样来写,也可以写成 \g{1]  ,\g{2},.....\g{9}。后面一种写法相对复杂些,但有助于perl来理解你想表达的含义。因为反斜杠在程序语言中有特殊的信念,通常表达转义,perl 在遇到反斜杠时,它会去猜你想表达的什么。所以如果你写一个类似: \123这样的东西,它就不知怎么去解析,你是想表达 \1+23,引用后面跟着数字,还是,\12+3,或 \123,转义符后面跟数字是可以表示转义一个8进制数字的。因此这里产生了歧义。perl 5.10 于是引入了 \g{N}这种表述方式来表示引用通配符。N 甚至可以是负数,当是用负数是,它表示一个相对位置。表示从当前位置开始往左数,第N个元组,如:

           "twooavvboonn"  =~ /tw(oo)a(vv)b\{-2}(nn)/   为true.


(7) 中括号[]: 中括号用来表示一个字符集合(character set)

     字符集合,顾名思义,就是字符的集合,集合的元素放在中括号里,表示每次匹配中其中的一个,如: "twoon” =~ /[tw]woo/ 为 true

     有时如果这个集合有很多元素,如26个字母,数字等,一个个地写在中括号里,未免太麻烦太蠢笨,这时可以用连字符(hyphen)来表示一个范围,如:[a-z]表示小写字母的集合,[a-zA-Z]表示大小写字母的集合。

     上面的用法用于提供范围来选择,但有时不匹配某个范围也是很常见的匹配需求,这时我们可以在集合的开头放一个脱字符 ^ (caret). 这种写法表示,匹配任何不在该集合中的字符,与上面的用法刚好相反。如:"twoon" =~ /[^two]woon/ 为false

               “ewoon" =~ /[^two]woon/ 为true

      由上面的用法,可知 ^,- 这两种符号在集合中有特殊含义,如果我们们想在集合中表示这两个字符,就也要转义一下。如:[\^ab\-]

      有些字符集合是很常用的,如字母,数字等,perl提供了一些缩写来表示这些常用的集合,如:\d表示一个数字,等价于[0-9],这些特殊字符包括如下 :

        \w -- (小写w) 表示字母或数字,等价于 [a-zA-Z0-9]

        \W -- (大写W)非字母且非数字,与\w相反

        \s  --  (小写s)匹配一个空格字符,包括:空格,换行,回车,tab,等价于[ \n\r\t\f]

        \S --  (大写S)匹配非空格字符,\s的相反

        \d -- 表示10进制数字,等价于 [0-9]


(8) 大括号:{}  

   大括号的作用是指定重复前面一个字符多少遍:

   {N} 重复N遍

   {n,m} 重复 n~m 遍

   {n,}  至少重复n遍

   {,m} 至多重复m遍

 示例:"twoon" =~ /two{2}n/    为true.


(9) ^,& 这两个通配符用来表示在匹配串的头部或尾部匹配。

     一般我们写这种: "twoon" =~ /oo/ 正则表达式的时候,匹配是从"twoon"的开始一路匹配下去,如tw != oo,就继续往下匹配,但有时候我们可能只想匹配一下开头或结尾,这时^,&就派上用场了。^用于匹配字符串的开关,&用于匹配字符串的结尾。如:  "twoon" =~ "^tw"  为true.

            “twoon” =~ “oo"   为true

            "twoon" =~ "^oo" 就为false.

            ”twoon" = "on&"  为true.

            "twoon“ = ”oo&"  为false


(10) “或" 通配符:  正则表达式用竖线 | 表示或, (ab | cd) 表示匹配竖线左右的字符组之一,如果左右的字符数超过一个,它必须和括号一起使用。

        如:    "twoon” =~ /t|ewoon/   结果为true

                    "twoon" =~ /(tw|ee)oon/  结果为true

                    "twoon" =~ /(ee|gs)oon/   结果为false

上面简单地介绍了正则表达式中各种通配符的含义及用法,可以看出,正则表达式在语法上还算是简单的,但这并不代表它也只会做简单的事情,事实上,正则表达式也可以写得很复杂,语法的简单或复杂与该语言功能强大与否并没有太多直接的联系。学习正则表达式可以让我们在很多场合下受益,特别是在使用unix类系统下的各种工具时,只是这种语言也和很多其它很多语言一样,学而不用就很容易忘。本文只是简单的介绍了一下它的基本语法,基本写法,要想做到熟能生巧,就需要在日常工作中,多练习,多操作,多留心了。

正则表达式的基本用法