【问题标题】:Regex to match a string with an even number of quotes正则表达式匹配带有偶数个引号的字符串
【发布时间】:2009-04-04 06:09:02
【问题描述】:

我想出了:([^"]*["][^"]*["][^"]*)*

它适用于所有情况,除了空字符串。我认为它会起作用,因为最后一颗星与前一个标记匹配 次或更多次。

有什么想法吗?

另外,如果有更好的方法,请告诉我并详细解释。

解决方案必须是正则表达式,因为使用它的地方是一个需要正则表达式的钩子。

它也必须匹配不带引号的字符串,因为零是偶数

【问题讨论】:

    标签: regex


    【解决方案1】:

    试试这个表达式:

    ^(?:[^"]+|"[^"]*")*$
    

    它匹配一个序列,该序列由除引号以外的任何字符 ([^"]+) 或一对带有除引号以外的任何字符的引号 ("[^"]*") 组成。 * 量词将空字符串考虑在内。

    【讨论】:

    • 您忘记详细解释它以及为什么我的不起作用。除了快速和肮脏的修复之外,我还想学习一些东西...... :-)
    • 你的不起作用,因为它要么匹配零个字符(组重复零次),要么匹配多个必须包含至少两个引号的字符(组重复一次)。所以不存在序列只是引号以外的字符的情况。
    • 大卫没有说任何关于匹配不带引号的字符串,但他也说他的正则表达式不匹配空字符串,这显然是匹配的。 @David,这是你真正想做的吗?
    • 不带引号的字符串有偶数个引号(0),所以应该匹配。
    【解决方案2】:

    您的正则表达式 应该 匹配完全空的字符串,但不匹配例如一个由单个空格组成的字符串,因为您的正则表达式指出如果字符串不是完全为空,则它需要包含至少一个双引号。这是因为正则表达式中的 ["] 标记后面没有 *.

    考虑所需正则表达式的正确方法如下:您要匹配(不带双引号的字符串)后跟(双引号)加上(不带双引号的字符串)后跟(双)引号后跟(字符串不带双引号),然后从第一个 'followed by' 开始无限重复。没有双引号的字符串是 [^"]*,所以你得到(为了可读性添加了空格):

    [^"]* (" [^"]* " [^"]*)*
    

    如果您将此与您的正则表达式进行比较,则第一个 [^"]* 已被移出 重复。

    【讨论】:

    • 我确实希望它匹配一个只有空格的字符串。事实上,任何不带引号的字符串都可以,因为它会有偶数个引号 (0)
    • 是的。我的回答是您在原始问题中给出的正则表达式与空字符串匹配,但它与没有任何双引号的非空字符串不匹配,这就是您的正则表达式的问题。
    【解决方案3】:

    似乎正则表达式不是适合这项工作的工具。编辑:但是,您似乎仅限于此。鉴于该限制,这并不能回答您的问题,但没有它也能很好地工作。

    只需遍历您的字符串并计数。 C 示例:

    bool hasEvenNumberOfQuotes(const char *str)
    {
        bool even = true;
    
        while(*str != '\0')
        {
            if(*str == '"')
                even = !even;
    
            ++str;
        }
    
        return even;
    }
    

    【讨论】:

    • 遗憾的是,我将使用代码的地方暴露了一个钩子,它是一个专门匹配或不匹配的正则表达式,所以只有一个正则表达式解决方案才能阻止我。
    • @Reis,不知道为什么当你说“另外,如果有更好的方法可以做到这一点,请告诉我并详细解释。”它回答了你的问题。请编辑您的问题,说明您只能使用正则表达式。
    • 为什么原始问题中没有这个细节?您已明确询问是否有更好的方法。
    • 我认为他的意思是更好的 regex
    【解决方案4】:

    根据您的正则表达式:

    ([^"]*["][^"]*["][^"]*)*
    

    添加线锚:

    ^([^"]*["][^"]*["][^"]*)*$
    

    增加匹配非"的可能性:

    ^([^"]*["][^"]*["][^"]*|[^"]?)*$
    

    这最后一步不允许匹配任何内容或消耗一个字符。这允许匹配缺少" 的字符串。请注意,需要行锚,否则子字符串将与此匹配。

    奖励:防止组反向引用(命名/编号组可能会稍微减慢正则表达式引擎):

    ^(?:[^"]*["][^"]*["][^"]*|[^"]?)*$
    

    【讨论】:

      【解决方案5】:
      import re
      
      def hasPairedQuotes(s):
          stripped = re.sub('[^"]', "", s)
          return len(stripped) % 2 == 0
      
      >>> hasPairedQuotes("")
      True
      >>> hasPairedQuotes('""')
      True
      >>> hasPairedQuotes('"""')
      False
      >>> hasPairedQuotes('"Hello world!""')
      False
      >>> hasPairedQuotes('"Hello world!"')
      True
      

      你想要一个正则表达式,这是一个正则表达式:^[^"]*("[^"]*")*[^"]*$... 但我认为易读性和可维护性的差异不言而喻。

      >>> re.match(r'^[^"]*("[^"]*"[^"])*$', 'Hello ""')
      <_sre.SRE_Match object at 0xb7cc0ce0>
      >>> re.match(r'^[^"]*("[^"]*"[^"])*$', 'Hello "" "')
      >>> 
      

      【讨论】:

      • 我什至不知道那是什么语言。也许是 Phyton?无论如何。它也对我没有帮助。
      • @Reis,PCRE 跨语言非常一致。不过,不同的正则表达式引擎可能会以不同的方式处理正则表达式,因此可能需要稍作修改。
      • 您需要将前导或尾随 [^"]*(但不是两者)移回括号内,以捕获引用部分之间的非引号。
      猜你喜欢
      • 2016-08-08
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多