【问题标题】:conditional regex on multiline string in pythonpython中多行字符串的条件正则表达式
【发布时间】:2022-06-10 17:21:03
【问题描述】:

这个问题和我原来的帖子很相似。

Unable to use conditional regex to test my string in python

再发一个新问题的原因是这里的要求和原来的有点不同。

如果给定的字符串是逐行的,那么原始答案就足够了。但是,那里的答案不能涵盖多行字符串的情况。见下文

Test case Test string Expect value from bool(re.match(...))
1. Naive match
xxxx
xxxx
board add 0/1 aaa
board add 0/2 aaa
board add 0/3 bbb
board add 0/4 bbb
board add 0/5 aaa
#
True
2. Bad model name
xxxx
xxxx
board add 0/1 xxx
board add 0/2 aaa
board add 0/3 bbb
board add 0/4 aaa
board add 0/5 bbb
#
False
3. Missing model
xxxx
xxxx
board add 0/2 aaa
board add 0/3 bbb
board add 0/4 bbb
board add 0/5 aaa
#
True

我尝试了多个正则表达式。但是,它们在任一测试用例 (2) / (3) 上都失败了。

Tried Regex Failed on Test
(board add 0/1)? (?(1) (aaa|bbb)) 2
^(?:(?!board add 0/1).)*$|board add 0/1 (?:aaa|bbb) 2
board add 0/1 (aaa|bbb) 3
(?=board add 0/1 )(?:board add 0/1 (aaa|bbb)) 3

是否可以编写一个正则表达式来通过测试用例?

您可以在以下网址查看它们

https://regex101.com/r/2l2Qd4/1

注意:

  • 我只想捕获特定的board add 0/1 而不是board add 0/\d+
    • 在我的实际使用案例中,接口可能需要不同的模型。这就是为什么我要为board add 0/1 找出一个特定的正则表达式

【问题讨论】:

    标签: python regex


    【解决方案1】:

    在这种情况下,你可以使用这个正则表达式

    board add 0/\d+ (?!aaa|bbb)
    

    如果正则表达式匹配,则字符串无效。

    Python 示例

    import re
    
    
    strings = [
        """xxxx
    xxxx
     board add 0/1 aaa
     board add 0/2 aaa
     board add 0/3 bbb
     board add 0/4 bbb
     board add 0/5 aaa
    #""",
        """xxxx
    xxxx
     board add 0/1 xxx
     board add 0/2 aaa
     board add 0/3 bbb
     board add 0/4 aaa
     board add 0/5 bbb
    #""",
        """xxxx
    xxxx
     board add 0/2 aaa
     board add 0/3 bbb
     board add 0/4 bbb
     board add 0/5 aaa
    #"""
    ]
    
    for string in strings:
        print(not bool(re.search(r"board add 0/\d+ (?!aaa|bbb)", string)))
    

    输出

    True
    False
    True
    

    说明

    re.search 按给定模式返回匹配的字符串块。如果不存在任何匹配项,则返回 None。该解决方案基于否定有效字符串。所以如果aaabbb 都没有跟在board add 0/1 之后,那么这个字符串是无效的。其余的将按照您在之前的question 中的描述进行传递。因此,如果re.search 返回除None 之外的任何值,则not bool(...) 会将值转换为预期结果。

    注意:我使用not bool(...),因为如果字符串不包含模式,则它是有效的。

    【讨论】:

    • 我不知道为什么re.search 会给你这个结果。但是,regex101 表明您的答案无法通过我编写的测试
    • @MondWan,我已经添加了解释。
    • 啊..我终于明白了。但是,为什么我们需要否定来解决这个问题呢?你介意解释一下为什么像(board add 0/1)? (?(1) (aaa|bbb)) 这样的正则表达式不能像第一位那样工作吗?
    • 第二,我试图通过(?!board add 0/\d+ (?!aaa|bbb)) 否定你的正则表达式。但是,它失败了。为什么不能这样做?
    【解决方案2】:

    您似乎想要匹配所有以 aaa 或 bbb 结尾的棋盘行,并在以非空白字符开头的字符串之间缩进。

    为防止部分匹配,您需要识别重复板部分之前和之后的部分。

    ^\S.*(?:\n[^\S\n]+board add 0/\d+ (?:aaa|bbb))+\n\S
    

    说明

    • ^ 字符串开始
    • \S.* 匹配一个非空白字符和该行的其余部分
    • (?:非捕获组作为一个整体重复部分
      • \n[^\S\n]+ 匹配换行符后跟 1+ 个空格
      • board add 0/\d+ (?:aaa|bbb) 匹配\d+ 匹配1+位数的棋盘图案
    • )+关闭非捕获组并重复1+次以匹配至少一行
    • \n\S 匹配换行符和非空白字符

    Regex demo

    【讨论】:

    • 抱歉问题中缺少要求。我已经更新了我的问题的要求。我需要特别抓住board add 0/1。因此,我尝试将\d+ 更改为1。但是,它没有按预期工作。最近,只有@ArtyomVancyan 的回答才能满足我的需求。
    猜你喜欢
    • 2020-05-05
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    • 2012-08-28
    • 2019-08-17
    • 2019-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多