Python / Regex-匹配两个字符之间的字符,匹配字符之前或之后的任何字符

时间:2018-06-25 13:59:20

标签: python regex

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

这里是一个例子:

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

相对于上述情况,我想匹配{{和}}之间带有短划线“-”的任何内容。

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

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

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

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

有人能看到我所缺少的吗?我了解为什么我的正则表达式无法按预期运行,但无法解决该问题。

谢谢

3 个答案:

答案 0 :(得分:3)

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

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

RegEx Demo

RegEx详细信息:

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

答案 1 :(得分:3)

使用

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 :(得分:0)

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

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

  • (...)创建一个捕获组,因此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']