【问题标题】:Python/Regex - match char between two chars, with anything before or after the matching charPython/Regex - 匹配两个字符之间的字符,匹配字符之前或之后的任何内容
【发布时间】:2018-06-25 22:37:53
【问题描述】:

我正在尝试匹配字符子集中的字符,其中匹配字符的任一侧都可以是任何东西。

这是一个例子:

{{ SITE_AGGREGATE_SUBNET }}.3 remote-as {{ BGP-AS }}

与上述相反,我想匹配 {{ 和 }} 之间带有破折号“-”的任何内容。

到目前为止,我的正则表达式模式是:

(?<={{)(.*?-.*?)(?=}})

但这会为返回的整个测试字符串创建一个匹配项:

SITE_AGGREGATE_SUBNET }}.3 remote-as {{ BGP-AS

有人能看到我错过了什么吗?我明白为什么我的正则表达式不能按预期工作,但不知道如何解决它。

谢谢

【问题讨论】:

    标签: python regex


    【解决方案1】:

    使用

    import re
    s = '{{ SITE_AGGREGATE_SUBNET }}.3 remote-as {{ BGP-AS }}'
    print([x.strip() for x in re.findall(r'{{(.*?)}}', s) if '-' in x])
    // -> ['BGP-AS']
    

    the Python demo

    详情

    • 仅使用{{(.*?)}} 正则表达式提取{{...}} 之间的所有匹配项(注意re.findall 只会返回捕获的子字符串,即与(.*?) 匹配的值)
    • 仅使用列表解析中的条件 (if '-' in x) 保留带有 - 的匹配项
    • 使用.strip() 删除尾随/前导空格

    单一的正则表达式方法(注意它可能效率较低):

    re.findall(r'{{\s*((?:(?!{{|}})[^-])*-.*?)\s*}}', s)
    

    Python demo

    详情

    • {{ - {{
    • \s* - 0+ 个空格
    • ((?:(?!{{|}})[^-])*-.*?) - 捕获组 1(re.findall 返回的内容):
      • (?:(?!{{|}})[^-])* - 一个 tempered greedy token 匹配任何非连字符字符,0+ 次,不开始 {{}} 子字符串
      • - - 一个连字符
      • .*? - 任何 0+ 字符(LF 除外),尽可能少
    • \s* - 0+ 个空格
    • }} - }}

    regex demo

    【讨论】:

      【解决方案2】:

      您可以将此正则表达式与负前瞻和捕获组一起使用:

      ({{(?:(?!{{|}})[^-])*)-(.*?}})
      

      RegEx Demo

      正则表达式详细信息:

      • (: 启动捕获组
        • {{:匹配{{
        • (?:: 启动非捕获组
          • (?{{|!}}):否定前瞻断言我们在下一个位置没有 {{}}
          • [^-]: 匹配除连字符以外的任何字符
        • )*:结束非捕获组。 * 匹配该组的 0+ 个实例
      • ): 结束捕获组
      • -:匹配文字连字符
      • (.*?}}):将剩余字符串匹配到 }},然后匹配 }} 并在第二个捕获组中捕获它

      【讨论】:

      • 这将匹配文本到破折号,但 OP 要求双括号内的整个字符串,只要所述字符串包含破折号
      • @anubhava.. 你能告诉我一个从正则表达式开始的好参考吗?
      • @DudeCoder:从regular-expressions.info 开始,这是一个学习正则表达式的好网站
      • @anubhava.. 谢谢你.. 但是是你开始学习正则表达式的那个网站吗?
      • 酷,太棒了
      【解决方案3】:

      您可以使用此模式:{{(.*?)}}

      • .*? 非贪婪匹配任何字符流。

      • (...) 创建一个捕获组,因此re.findall 产生括号内。

      要检查匹配是否包含'-',使用in 可能更简单。

      代码

      import re
      
      def tokenize(s):
          return [w.strip() for w in re.findall('{{(.*?)}}', s) if '-' in w]
      
      print(tokenize('{{ SITE_AGGREGATE_SUBNET }}.3 remote-as {{ BGP-AS }}'))
      

      输出

      ['BGP-AS']
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-13
        • 1970-01-01
        • 2013-11-08
        • 2021-12-01
        • 2011-09-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多