【问题标题】:REGEX (PCRE) matching only if zero or onceREGEX (PCRE) 仅在零或一次时匹配
【发布时间】:2010-11-11 19:11:59
【问题描述】:

我有以下问题。

让我们输入(wikitext)

======hello((my first program)) world======

我想匹配“hello”、“my first program”和“world”(注意空格)。

但是对于输入:

======hello(my first program)) world======

我想匹配“hello(my first program”和“world”。

换句话说,我想匹配任何字母、空格以及任何单个符号(没有双倍或更多)。

这应该使用诸如 \p{L}、\p{S} 或 \p{Z} 等 unicode 字符属性来完成,如 here 所记录的那样。

有什么想法吗?

附录 1

正则表达式必须在 unicode 术语中的任何双符号或标点符号之前停止,即在任何 \p{S}{2,} 或 \p{P}{2,} 之前。

我不想用这个来解析整个 wikitext,请仔细阅读我的问题。我正在寻找的正则表达式是我正在研究的词法分析器,并且使其与此类输入匹配将难以置信地简化我的解析器。

附录 2

该模式必须与preg_match() 一起使用。我可以想象我将如何首先拆分它。也许它会使用一些前瞻性,我不知道,我已经尝试了我能想象的一切。

仅使用preg_match() 是当前的词法分析器实现的固定要求。一定是这样,因为这是词法分析器工作的自然方式:它们匹配输入流中的序列。

【问题讨论】:

    标签: php regex pcre


    【解决方案1】:
    return preg_split('/([\pS\pP])\\1+/', $theString);
    

    结果:http://www.ideone.com/YcbIf

    (您需要手动删除空字符串。)


    编辑:作为preg_match 正则表达式:

    '/(?:^|([\pS\pP])\\1+)((?:[^\pS\pP]|([\pS\pP])(?!\\3))*)/'
    

    在匹配时获取第二个捕获组。示例:http://www.ideone.com/ErTVA

    但是您可以只使用 ([\pS\pP])\\1+ 并丢弃,或者如果不匹配,则使用 (?:[^\pS\pP]|([\pS\pP])(?!\\3))* 并记录,因为您的词法分析器将使用超过 1 个正则表达式?

    【讨论】:

    • 如果您可以在问题中考虑“附录 2”,那就太好了。仅使用 preg_match() 是当前词法分析器实现的一个固定要求。一定是这样,因为这是词法分析器工作的自然方式:它们匹配输入流中的序列。
    • 谢谢,'/((?:[^\pS\pP]|([\pS\pP])(?!\\2))*)/mu' 做到了。我不需要匹配“======”,因为词法分析器已经匹配了它,然后它将词法分析器置于尝试匹配您刚刚给我的正则表达式的上下文中。无论如何,这解决了我的问题。
    【解决方案2】:

    众所周知,正则表达式被过度使用并且不适合解析这样的语言。你可以暂时摆脱它,但最终你会发现一些东西会破坏你的解析器,需要一个又一个的调整和一个庞大的单元测试库来确保合规性。

    您应该认真考虑编写适当的词法分析器和解析器。

    【讨论】:

    • 这实际上是针对我正在编写的词法分析器。匹配的字符串将是一个标记。如果我设法在词法分析器中做到这一点(使用我现在正在寻找的正则表达式),解析器将非常简化。
    • 在编写词法分析器时,您通常会读取一个字符并决定如何处理它,然后再读取另一个字符。在解析阶段,您将确切地决定如何处理这种情况,但是对于第二个示例,词法分析器应该只返回像(在伪代码中)[LEVEL_6_HEADING, TEXT("hello"), LPAREN, TEXT("my first program"), RPAREN, RPAREN, LEVEL_6_HEADING] 这样的标记。解析器需要理解这些标记。
    • 我知道经典词法分析器是如何工作的。我正在研究的不是经典的。 “用户”将能够连接到它(因此这里不涉及“词法分析器生成器”)。看,我不是在寻找关于做什么和不做什么的建议,我已经知道我的要求,我做的方式是唯一最好的。我只是在寻找一种模式。
    • 明白。我只是看到很多这样的问题,通常编写解析器的人认为正则表达式是编写解析器的唯一方法。我喜欢尽可能地把他们推向正确的方向。不应暗示对您的方法的判断。
    猜你喜欢
    • 2018-03-28
    • 2021-06-13
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2020-02-09
    • 2012-04-15
    相关资源
    最近更新 更多