【问题标题】:Regex strange behavior正则表达式奇怪的行为
【发布时间】:2013-07-09 14:50:57
【问题描述】:

我正在尝试创建一个 C#/WPF 解析器。我对正则表达式有很好的全面了解,因为这不是我的第一个解析器(也可能不会是我的最后一个)

但是,现在我有一个非常奇怪的行为。这是我要解析的内容(注意:实际数据已删除,我只是按照与我相同的结构创建了一个字符串):

aaaaa bbbbb 50 c blabla

我的应用程序会收到我只想拆分和识别的行。由于某种原因,空格的数量是可变的(一个在 aaaa 和 bbbb 之间,两个在 bbbb 和 50... 之间)。 (在人们告诉我之前请注意:我不会使用 string.Split()。因为我有很多不同的线结构,我应该总是从中得到相同的数据。只是拆分它会让我无法识别每个部分意思)

我目前的测试正则表达式有点简单:

(\S*)[\s*](\S*)[\s*](\S*)[\s*](p|c)(.*)

现在,这就是发生的事情。当 bbbbb 和 50 之间只有一个空格时,正则表达式会正确解析(注意:我使用 http://www.myregextester.com/index.php 来测试我的正则表达式)

$matches Array:
(
    [0] => Array
        (
            [0] => aaaaa bbbbb 50 c  blabla
        )

    [1] => Array
        (
            [0] => aaaaa
        )

    [2] => Array
        (
            [0] => bbbbb
        )

    [3] => Array
        (
            [0] => 50
        )

    [4] => Array
        (
            [0] => c
        )

    [5] => Array
        (
            [0] =>   blabla
        )

)

如果在 bbbb 和 50 之间有 两个空格,会发生以下情况:

$matches Array:
(
    [0] => Array
        (
            [0] => bbbbb  50 c blabla
        )

    [1] => Array
        (
            [0] => bbbbb
        )

    [2] => Array
        (
            [0] => 
        )

    [3] => Array
        (
            [0] => 50
        )

    [4] => Array
        (
            [0] => c
        )

    [5] => Array
        (
            [0] =>  blabla
        )

)

现在我知道我可以轻松地从行中删除不需要的空格(这是我目前所做的)。无论如何,我很想了解我在那里错过了什么:为什么当我添加一个额外的空格时会发生这种情况,应该用我添加的 [\s*] 之一来识别?

谢谢!

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    [\s*] 没有按照您的预期进行。方括号表示一个字符组,这意味着它将匹配\s(空格)或literal *的字符。

    只需删除这些括号即可获得预期的行为:匹配 \s(空格)0 次或更多次:

    (\S*)\s*(\S*)\s*(\S*)\s*(p|c)(.*)
    

    编辑:Jesse 的评论也很有价值:除非某些组确实是可选的,否则您可能希望使用 + 而不是 * 量词。

    【讨论】:

    • 谢谢!我不知道我不能在方括号中使用 *。至于星星,现在肯定太多了(虽然有些组是可选的),我确实会尽可能地使用+
    • @Damascus 您在这里应该明白的是,正则表达式的语法非常严格。这些方括号具有非常独特的含义,您不能随时将它们换掉。将* 放置在 字符组中时,这很有意义,因为字符组本身只会匹配一个 字符。
    【解决方案2】:

    每当我看到正则表达式中的星星时,我都会畏缩。星匹配零个或多个,真的会让你绊倒!将* 的所有实例替换为+,然后重试。当然,除非其中一些分组确实是可选的。

    编辑:其他答案非常正确地指出您使用的是字符组,但我的观点仍然存在:注意*

    【讨论】:

    • 你说得对。我从 * 开始,因为我不知道某些组是否是可选的,我很快就陷入了 * 漩涡!我将 * 留给可选组,谢谢!
    【解决方案3】:

    您需要将[\s*] 替换为\s+

    [\s*] 表示“一个空格字符或一个星号”。

    \s+ 表示“一个或多个空白字符”,这是您想要的。

    Character classes 是很多人都搞错的东西。

    【讨论】:

      【解决方案4】:

      [\s*] 有不同的含义,因为它在方括号内 [\s]+ 会表现出您想要的行为,或者 [\s]{1,} 此表达式将匹配空白字符 1 次或多次。您还需要记住,根据您使用的功能,您可能需要启用“g”标志,它是全局标志,以使您的正则表达式匹配您希望解析的所有出现的模式,否则它可能只解析第一个匹配。括号否定大多数字符类并将大多数修饰符转换为文字,除了少数例外访问 MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions 查看您对正则表达式在括号内的行为或正则表达式上的 PHP API 的知识http://php.net/manual/en/reference.pcre.pattern.syntax.php

      【讨论】:

        猜你喜欢
        • 2018-06-03
        • 1970-01-01
        • 1970-01-01
        • 2012-09-17
        • 2013-07-13
        • 2012-03-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多