【问题标题】:How to find all instances of two digits after ">" or "<" for a particular variable but not for other variables如何查找特定变量的“>”或“<”之后的所有两位数实例,但不查找其他变量
【发布时间】:2021-07-12 14:14:10
【问题描述】:

在我的示例中,所有年龄都在1099 之间。我想找到变量“age”的所有实例都是&gt;&lt;,而不是两位数。我需要知道等号和两位数。如果它们对应于不同的变量(例如,身高或体重),我不想要等号和两位数。为简单起见,所有年龄、身高和体重都是两位数。没有单位。

sample_text = "age > 10 but can be > 20 or > 22 - if the height is > 60 then age can be > 30, otherwise it must be < 35"

我正在寻找的输出是age_list,看起来像[("&gt;", "10"), ("&gt;", "20"), ("&gt;", "22"), ("&gt;", "30"), ("&lt;", "35)]。列表应该可以是任意长度。

当格​​式总是“年龄”后跟符号后跟数字时,很容易得到它们。我使用了下面的代码,它提取了[("&gt;", "10"), ("&gt;", "30")],但我无法获得其他数字——例如,显然与年龄相关的2022。我需要得到这些,但要避免 60 与身高挂钩(如果有重量,任何与体重挂钩的数字)。

re.findall("age\s*[a-zA-Z\s]*(>|<)\s*(\d\d)", sample_text)

当格​​式为“年龄符号数字或某些符号数字”时,我有使用re.search 的变通方法,但如果有一堆符号和数字前面没有“年龄”,则变通方法会失败 -例如,“年龄必须 > 20 或者如果这个则 > 24 或者如果那个则 > 30...”

【问题讨论】:

  • “年龄”、“身高”和“体重”是唯一可能的变量吗?
  • 在这个例子中是的。我可以想象其他项目有更多复杂的变量(即,我不想捕获数字的变量)。但我希望/认为同样的原则也适用。
  • 好的,这绝对有帮助!但是,如果您需要涵盖诸如“年龄必须> 20,或者如果此年龄> 24”之类的内容,我认为正则表达式不会成功。你需要一个完整的自然语言处理/理解管道..

标签: python regex regex-group


【解决方案1】:

你可以先调整匹配从年龄开始,不要交叉匹配heightwidth

\bage(?:(?:(?!\b(?:height|weight)\b)[^<>])*[<>]\s+\d+)+

模式匹配:

  • \bage 匹配 age 前面有一个单词边界
  • (?:外部非捕获组整体重复
    • (?:内部非捕获组整体重复
      • (?!\b(?:height|weight)\b) 否定前瞻,不直接向右断言 heightweight 并使用单词边界来防止部分匹配
      • [^&lt;&gt;] 匹配除 &lt;&gt; 之外的任何字符
    • )*关闭内部非捕获组并可选择重复
    • [&lt;&gt;]\s+\d+ 匹配 &lt;&gt; 然后 1+ 空白字符和 1+ 数字
  • )+关闭外部组并重复1次以上

Regex demo | Python demo

使用 2 个捕获组与 re.findall 和 ([&lt;&gt;])\s+(\d+) 匹配的过程,捕获第 1 组中的符号和第 2 组中的数字

import re

pattern = r"\bage(?:(?:(?!\b(?:height|weight)\b)[^<>])*[<>]\s+\d+)+"
s = ("age > 10 but can be > 20 or > 22 - if the height is > 60 then age can be > 30, otherwise it must be < 35\n")

for m in re.findall(pattern, s):
    print(re.findall(r"([<>])\s+(\d+)", m))

输出

[('>', '10'), ('>', '20'), ('>', '22')]
[('>', '30'), ('<', '35')]

【讨论】:

  • 非常有帮助,谢谢。在这里学习很多。我看到 \b 要求提取的文本以年龄开头。我还看到了负前瞻以避免身高|体重。 “[^]”是说避免跟随身高或体重的文字吗?我需要研究它和嵌套的未捕获组(使用“?:”)。
  • @vintagedeek \b 是单词边界,[^&lt;&gt;] 是否定字符类。我现在不在我的机器后面,但我稍后会添加解释。
【解决方案2】:

你可以试试这个

import re
sample_text = "age > 10 but can be > 20 or > 22 - if the height is > 60 then age can be > 30, otherwise it must be < 35"
matched = re.findall(r'[<>]|[\d]+', sample_text)
results = []
for i in range(0, len(matched) - 1, 2):
    results.append((matched[i], matched[i+1]))
print(results)
# output: [('>', '10'), ('>', '20'), ('>', '22'), ('>', '60'), ('>', '30'), ('<', '35')]

【讨论】:

    猜你喜欢
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 2015-03-07
    • 2020-03-22
    • 2022-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多