【问题标题】:How to specify what not to match on regex如何在正则表达式上指定不匹配的内容
【发布时间】:2019-03-26 20:57:21
【问题描述】:

免责声明:此问题已重做,因此 cmets 和答案可能看起来无关。抱歉,我这样做是为了让问题更清晰、结构更好。

假设给定字符串,我想在其中找到两个不同的组(名称), 其中一组 A 满足条件 1,组 B 满足条件 2 还有条件1。

举个例子:假设我有一个数学函数-

'[class.parameterA] * numpy.exp( [x]*module.constantA - constant_B/[x] ) + [parameter_B]'

-我控制参数的值,但不控制常量的值。 我想(通过使用re.findall())获得一组常量 和一组参数。

>>> group1
['numpy.exp', 'module.constantA', 'constant_B']
>>> group2
['class.parameterA', 'x', 'x', 'parameter_B']

我知道对于这种特殊情况我不应该 匹配numpy.exp,但为了问题的目的,我允许 这是一场比赛。

为了澄清,这个问题旨在寻求“忽略匹配 {sequence}”的表示 在正则表达式中并知道是否有可能以“仅满足条件 1”而不是“满足条件 1 而不是条件 2”的方式解决问题,因此该解决方案可以扩展到多个条件。请提供一个部分抽象的答案(不是对这个例子过于具体)。

当然,过了一段时间,我只能为其中一个小组找到部分解决方案(参见奖励),但非常欢迎任何其他明确的解决方案:

c1 = r'\w+\.?\w*' # forces alphanumeric variable structure
# c1 = r'[\w\.\(\)]*?' allows more freedom (can introduce function calls)
# at the cost of matching invalid names, like class..parameterA
c2 = r'(?<=\[)', r'(?=\])'

re_group2 = c2[0] + c1 + c2[1]

>>>> re.findall(re_group2, func)
['class.parameterA', 'x', 'x', 'parameter_B']

显然直观的括号否定不适用于group1,但我可能介绍不正确:

c1 = r'\w+\.?\w*'
nc2 = r'(?<!\[\w)', r'(?!\w\])' # condition 2 negation approach

re_group1 = nc2[0] + c1 + nc2[1]

>>> re.findall(re_group1, func)
['class.parameterA', 'numpy.exp', 'x', 'module.constantA',
'constant_B', 'x', 'parameter_B']

奖励:如果有,比如说,module.submodule.constantA(超过 1 个点),正则表达式会如何变化? 我想c1 = r'\w+(\.\w+)*',但它并没有达到我的预期。编辑:我需要使用非捕获组,因为我使用的是re.findall。所以c1 = r'\w+(?:\.\w+)*'

【问题讨论】:

  • 你能再举几个例子吗?
  • @jrook 我一直在搞乱代码,发现了几个错误;给我一些时间来重新思考这个问题,这样就值得花时间正确解决问题。
  • 你可以试试这个吗?使用 double findall [^-+* ]+(?= \*) , (?&lt;=\[).*?(?=\])。一个用于g1 另一个用于g2
  • @kcorlidy 它有效,但我想我不明白,或者我忘记了.*? 的多种语法。这是否意味着括号之间需要 0 或 1 个任意数量字符的“刚性”字符串?这些组合的限制是什么?但是,如果我将rho_1 * x 更改为rho_1 / x,g1 即使在将/ 添加到第一部分之后也会跳过rho_1(-+* 例外)。 g2 似乎在各种不同的情况下都能完美运行,这正是我最初所寻找的。​​span>
  • 这与 .*? and .* 不同。用我的话来说,这意味着尽可能少地匹配字符串

标签: python regex regex-negation


【解决方案1】:

我做了两个更改:我将搜索锚定在单词的开头,并将您的第一个断言转换为后向断言。我在 Notepad++ 中尝试过(这里没有 Python),它适用于示例

\b(?&lt;!\[)[a-wzA-Z_0-9]+(?!\])

我希望你的公式有一致的间距...

【讨论】:

  • 我的输出是['rho_1', 'R', 'p']。我想我正在尝试获取“任何字母数字(字母 x 和 y 除外)字符串,但忽略方括号之间的所有内容”的正则表达式。我将重做该问题,以尝试更好地了解该问题。
  • 问题已编辑,您可能想再试一次?
【解决方案2】:

使用双 findall 会很棒。

import re
a = "rho_1 * x + R * [np.R] + rho_1 / x + R * [np.R]"

print(re.findall(r"\w+(?= \*| \/)",a))
print(re.findall("(?<=\[).*?(?=\])",a))
  1. 第 1 组
    • \w+ 匹配非字母数字字符,不包括“_”
    • (?= *| /) 字符串以*/ 结尾
  2. 第 2 组
    • (?[ 开头
    • .*?尽可能少匹配任何字符
    • (?=]) 以] 结尾

【讨论】:

  • 对问题进行了编辑以使其更清楚,对于给您带来的不便,我们深表歉意。
  • @mariogarcc r'\w+(\.\w+)*' 将显示匹配的部分内容。我的意思是它匹配你想要的,但是这个正则表达式只会显示最后一个匹配的组(优先级)。您应该尝试(\w+(\.\w+)*) 了解更多信息,我认为它会比我说的更好。
  • @mariogarcc 可能你可以阅读regular-expressions.info/lookaround.html
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-24
  • 1970-01-01
  • 1970-01-01
  • 2018-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多