欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

浅议正则表达式中的 “竖线(|)”

1.  前言

这两天有点空,但是也不能这么闲着啊。所以就翻了翻 <<精通正则表达式>> 一书。 发现了很多自己不了解的东西(汗颜阿,自己知道的东西太少了!)。其中"|"就是其中一个。不懂就补吧,所以就有了下面的一点记录。

2. 用途

| ” 他的意思就是 “ ” 。 用他我们可以把不同的 子表达式 合成一个总表达式,而这个总的表达式可以匹配 任意一个 的子表达式。我觉得下面有几个名称需要解释一下。

  • 子表达式

  • 表达式中被 “ ” 分格开的部分。如图 中的 “Back ” 、 “Go ” 和 “Do ” 就分别是一个子表达式。(这里对子表达方式的定义只是适用于多选结构)

  • 任意一个

  • 表示该表达式可以匹配上例中的 “Back ” 、 “Go ” 或 “Do ” 中的任何但是 只能是一个 。 也就是说他不能匹配 “BackDo ” 或 “GoDo ” 这样的字符串。

下面我们就举几个例子来说明他的用法。

  • Jettery|Jettrey ” 和 “Jett(er|re)y ”

  • 看看 “Jettery|Jettrey ” 和 “Jett(er|re)y ” 之间有什么区别。他们匹配的结果是否相同? 如果从匹配结果来看的话他们是等价的。都能够匹配“Jettery”或“Jettrey”。但是过程确实不一样的。在 “Jettery|Jettrey ” 中我们可以很容易的区分出子表达式分别是 “Jettery ” 和 “Jettrey ” 。但是在 “Jett(er|re)y ” 中就不是这个样子了。他的子表达式分别是 “er ” 和 “re ” ,为什么他们的子表达式是 “er ” 和 “re ” 而不是 “Jett(er ” 和 “re)y ” 呢?上面不是说子表达式是被 “| ” 分隔开的部分吗。在这个表达式中 “Jett(er ” 和 “er)y ” 的确是被 “| ” 分隔开的两个部分啊?。对这个没有错,但是因为 “() ” 的存在改变了 “| ” 的作用范围。那么在这个表达式中 “| ” 的作用范围就只是 “(erre) ” 了。在这个范围中就符合我们上面对于子表达式的定义了。我们可以通过下面这两个图来证明这一点。

    Jettery 和 Jettrey 分别为子表达式

     

    总表达式由三个部分组成:

    • Jett:用于匹配开头的“Jett”

    • (er|re):这是一个可以被捕获的子表达式。这个是子表达式就是 “ ” 元字符的操作范围。 “er ” 和 “re ” 就成被 “| ” 分开的两个子表达式。就是图中1所匹配的内容了。

    • y : 匹配最后的y。

     

     

    Note
    [Note]

    (...) ”元字符可以改变“ ”元字符的作用范围。

  • From|Subject|Data:.* ”和“(From|Subject|Data):.* ”

  • 这两个表达式一样吗?如果不一样,他们的区别在什么地方呢?事实上这两个表达式有着很大的差别。这一点从匹配的结果就可以看出来。 例如第一个表达式能够匹配“Data: Mon ,23 Oct ”,但是却不能匹配“From: JetGeng@hotmail.com ”。 但是第二个却可以。问题处在那里呢。还是“(...) ”改变了"|"的作用范围。

 

3. 体会

在正则表达式中使用“| ”元字符的时候一点先要确定“| ”的作用范围, 根据这个作用范围判断出被分成的子表达式。这样就可以确保“| ”能够返回给你你需要的东西。

Note

[Note]

如果使用NFA引擎类型的正则表达式驱动,注意分支不宜太多,否则会引起性能问题。具体的原因可能的话再另外再写。

来自  http://jet-geng.iteye.com/blog/466621

普通分类: