洛阳铲的日志

2012年03月8日

Preg正则表达式高级语法

Filed under: 生活小札 — 洛阳铲 @ 17:36

不得不承认perl的正则表达式是史上最强悍的语言规则描述符,无论python、还是php、还是ruby都统统向preg靠拢,由此可见一 斑。
这儿说些高阶的正则表达式运用

1. 表达式内部选项
    1.1 表达式内部可以设置一些选项(i,m,s,x,U,X),设置方法为'(?’和’)’之间,并且对之后的这些选项之后的表达式产生影响,比如:
    (?U)或者他们的组合(?imU)。比如 /ab(?i)c/ 只匹配 “abc” 和 and “abC”。 
    12    而且可以使用’-‘来取消对应的选项,比如(?im-U)。
    1.3    如果这些选项设置是出现在子模式内部,则只对该子模式产生影响。比如:(a(?i)b)c 只匹配 “abc” 和 “aBc”。不会匹配abC和aBC
    1.4    子模式中,选项后面的表达式都会受影响,这很重要,因为同一个子模式中,
选项后面的分支表达式‘|’也会受影响。比如: (a(?i)b|c) 将匹配 “ab”,”aB”,”c” 和 “C”。
   
2. 表达式子模式
2.1.  正则表达式除了参见的以用’/reg/’标识外,还可以用非字母数字分隔符比如:#,+,~等等符号,比如: #[0-9]#或者~[a-z]~标识
2.2.  (a+)表示子模式捕获,
表示匹配a开头的,可以通过反向引用1来标识被匹配到的内容,比如匹配’aaa’时,1为’aaa’, 是贪婪匹配(未设置U)。
    而(a+?)则是非贪婪,对应的1为’a’;
2.3.   正则表达式的反向引用: 1,2等等常常原来反向引用,这个不仅仅可以用在应用匹配结果,也可以用在表达式中间本身,
    比如:~(((?i)rah)s+2)~ 匹配 ‘RAH RAH’和’rah rah’,但是不会匹配’RAH rah’
2.4.     (?P<name>a+),则会为1取一 个名字叫name,这是子模式命名捕获
2.5.     (?:a+),表示需要子模式,但是不捕获,

2.6      进一步,非捕获子模式表达式的内部选项如何设置?按照正常的做法是(?:(?i)xxxxxxxx),’?:‘ 表示非捕获,’?i‘表示内部的i选项,两个括号很繁琐,可以简写为: (?i:xxxxxx)
        比如:/(?i:saturday|sunday)/匹配不分大小写的saturday和sunday而且不会捕获。

一个综合使用这些技巧的例子是:
preg_match(‘~the (?P<full_name>(?:red|white) (?P<title>king|queen))~‘,”the white queen”, $matches);
最后 $matches的结果为:
array(5) {
  [0]=>
  string(15) “the white queen”
  [“full_name”]=>
  string(11) “white queen”
  [1]=>
  string(11) “white queen”
  [“title”]=>
  string(5) “queen”
  [2]=>
  string(5) “queen”
}

3.
子模式断言: 测试某个表达式以某字符串开头(preceding)或者结尾(following),重要的是它不占用任何的字符串,这里面就有四种结果了:
3.1. 是以字符串结x尾: (?=x)
3.2. 不以字符串结x尾:  (?!x)
3.3. 是以字符串x开头: (?<=x)
3. 4. 不以字符串x开头: (?<!x)
比如要把字符串:  f1:a|f2:b|f3[|]  , 用竖线’|’分割成数组,但是在方括号内的竖线’|’不要分割,
使用表达式: /(?<![)|(?!])/ 即可,两个否定断言:前向和后向的就可以搞定。
多个断言可以同时以任意顺序出现,比如:  /(?<=d{3})(?<!999)foo/会匹配除999以外的三位数开头的foo,但是不会匹配234abcfoo
多个断言可以嵌套: /(?<=(?<!foo)bar)baz/, 匹配以bar开头的baz,但是要求bar不以foo 开头,

没有评论 »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress