【问题标题】:Extract exact words or set of characters using Regex in Python在 Python 中使用 Regex 提取准确的单词或字符集
【发布时间】:2020-08-11 21:19:53
【问题描述】:

假设我有一个这样的列表。

List = ['MX_QW-765', 'RUC_PO-345', 'RUC_POLO-209']. 

我想搜索并返回“PO”所在的匹配项。从技术上讲,我应该将RUC_PO-345 作为我的输出,但即使RUC_POLO-209 也会与RUC_PO-345 一起作为输出返回。

【问题讨论】:

  • 你能分享一下正则表达式吗?
  • 你的匹配标准是什么?到目前为止,您尝试过什么?
  • 这能回答你的问题吗? whole word match in javascript
  • 您需要在单词周围的正则表达式中使用分词符 (\b)。这将阻止 cat 匹配 caterpillar
  • 这简直太奇怪了,您正在列表中搜索单词“cat”,如果找到了想要返回“cat”?为什么Regex?为什么不简单地检查您的话是否是in 列表?我认为您在这里使用了错误的方法...

标签: python regex filter string-matching


【解决方案1】:

您应该使用regular expression (import re),这是您应该使用的正则表达式:r'(?<![A-Za-z0-9])PO(?![A-Za-z0-9])'

我之前推荐了 \b 特殊序列,但事实证明 '_' 被认为是单词的一部分,而你的情况并非如此,所以它不起作用。

这给您留下了一些更复杂的负面预测和负面预测断言,这分别是 (?<!... 和 (?!... 。要了解它们的工作原理,请阅读 Python 正则表达式的文档。

【讨论】:

  • 注意_(下划线)`被认为是一个字字符(因此它在\w[a-zA-Z0-9_]范围内。这正是子字符串前面的字符OP 对...感兴趣。您提出的解决方案将不起作用。例如,在 here 中尝试。
  • r‘_RO\b’ 可以匹配,如果你想使用单词边界特殊。
  • @JvdV - Grr。 sigh 好吧,那么剩下的就是否定的后视和否定的前瞻断言。我会修正我的答案。
【解决方案2】:

图案:

‘_PO[^\w]’

应该使用 re.search() 或 re.findall() 调用;它不适用于 re.match,因为它不考虑字符串开头的字符。

模式如下:匹配1个下划线('_')后跟1个大写P('P')后跟1个大写O ('O') 后跟 一个非单词字符的字符。特殊字符“\w”匹配[a-zA-Z0-9_]

‘_PO\W’

^ 这也可以用作建议的第一个模式的较短版本(信用 @JvdV in cmets)

‘_PO[^A-Za-z]’

此模式使用“字符集而不是字母字符”。如果破折号会干扰前两种模式中的任何一种。

要使用它来识别列表中的模式,您可以使用循环:

import re

For thing in my_list:
    if re.search(‘_PO[^\w]’, thing) is not None:
        # do something
        print(thing)

这将使用re.search 调用将模式匹配为if 条件中的True 条件。当 re 不匹配一个字符串时,它返回 None;因此...if re.search() is not None的语法。

希望对你有帮助!

【讨论】:

  • 这可以简化为_PO\W,但我认为应该是环视的一个很好的替代方案=)。赞成
  • 在正文中添加了您的建议,并带有@credit 给您。好建议!
  • 请不要提及我。这是积极的批评,我们的目标是共同提供更好、更简洁的答案。
  • 不不,这是一个很好的补充,我很感激!
【解决方案3】:

更新前的问题:

根据我的评论,我认为您使用了错误的方法。在我看来你可以简单地使用in:

words = ['cat', 'caterpillar', 'monkey', 'monk', 'doggy', 'doggo', 'dog']
if 'cat' in words:
    print("yes")
else:
    print("no")

返回:yes

words = ['cats', 'caterpillar', 'monkey', 'monk', 'doggy', 'doggo', 'dog']
if 'cat' in words:
    print("yes")
else:
    print("no")

返回:no


更新后的问题:

现在,如果您的示例数据并未真正反映您的需求,但您有兴趣在列表元素中查找子字符串,您可以尝试:

import re
words = ['MX_QW-765', 'RUC_PO-345', 'RUC_POLO-209']
srch = 'PO'
r = re.compile(fr'(?<=_){srch}(?=-)')
print(list(filter(r.findall, words)))

或者使用match:

import re
words = ['MX_QW-765', 'RUC_PO-345', 'RUC_POLO-209']
srch = 'PO'
r = re.compile(fr'^.*(?<=_){srch}(?=-).*$')
print(list(filter(r.match, words)))

这将返回遵循该模式的项目列表(在本例中为 ['RUC_PO-345'])。我使用上述常规模式来确保您的搜索值不会位于搜索字符串的开头,而是在下划线之后,然后是 -


现在,如果您有想要查找的产品列表,请考虑以下内容:

import re
words = ['MX_QW-765', 'RUC_PO-345', 'RUC_POLO-209']
srch = ['PO', 'QW']
r = re.compile(fr'(?<=_)({"|".join(srch)})(?=-)')
print(list(filter(r.findall, words)))

或者再次使用match:

import re
words = ['MX_QW-765', 'RUC_PO-345', 'RUC_POLO-209']
srch = ['PO', 'QW']
r = re.compile(fr'^.*(?<=_)({"|".join(srch)})(?=-).*$')
print(list(filter(r.match, words)))

两者都会返回:['MX_QW-765', 'RUC_PO-345']

请注意,如果您不支持 f 字符串,您也可以将变量连接到模式中。

【讨论】:

  • 一些随机查询。假设我有一个像这样的列表 List = ['MX_QW-765', 'RUC_PO-345', 'RUC_POLO-209']。如果我在此应用相同的逻辑并仅搜索包含“PO”的字符串,从技术上讲,我应该将“RUC_PO-345”作为我的输出,但即使是“RUC_POLO-209”也会与“RUC_PO-”一起作为输出返回345'。
  • @Rick,对我来说没有任何回报,因为PO 不在列表中。但是您现在要从完整字符串匹配到子字符串匹配......它是哪一个?您的示例数据似乎不能反映您的实际需求。
  • 你能帮我解决这个问题吗?如何处理像这样的子字符串匹配?
  • @Rick,我已经用可能的多种处理这种情况的方法之一更新了我的答案。如果你没有 f 字符串,你也可以连接你的模式。
【解决方案4】:

我们可以尝试在我们的正则表达式字符串中匹配 'cat'、'dog'、'monk' 三个精确单词之一。

我们的正则表达式字符串将是"\b(?:cat|dog|monk)\b"

\b 用于定义单词边界。我们使用\b,以便我们可以搜索整个单词(这正是您面临的问题)。添加这将不匹配 tomcatcaterpillar 并且只有 cat

接下来,(?:)被称为非捕获组(解释为here

现在我们需要匹配catdogmonk 之一。所以这表示为cat|dog|monk。在 python 3 中,这将是:

import re

words = ['cat', 'caterpillar', 'monkey', 'monk', 'doggy', 'doggo', 'dog']
regex = r"\b(?:cat|dog|monk)\b"

r=re.compile(regex)
matched = list(filter(r.match, words))

print(matched)

要通过可迭代列表实现匹配正则表达式,我们使用 Stackoverflow 答案 here 中提到的 filter 函数

你可以找到可运行的Python code here

注意:最后,regex101 是一个很棒的在线工具,可以尝试不同的正则表达式字符串并实时获得解释。我们的正则表达式字符串的解释是here

【讨论】:

    【解决方案5】:

    您需要添加一个 $ 符号来表示字符串的结尾,您还可以添加一个 ^ 这是字符串的开头,因此只有 cat 匹配:

     ^cat$
    

    【讨论】:

      【解决方案6】:

      尝试使用列表中的搜索词构建正则表达式替换:

      words = ['cat', 'caterpillar', 'monkey', 'monk', 'doggy', 'doggo', 'dog']
      your_text = 'I like cat, dog, rabbit, antelope, and monkey, but not giraffes'
      regex = r'\b(?:' + '|'.join(words) + r')\b'
      print(regex)
      matches = re.findall(regex, your_text)
      print(matches)
      

      打印出来:

      \b(?:cat|caterpillar|monkey|monk|doggy|doggo|dog)\b
      ['cat', 'dog', 'monkey']
      

      您可以清楚地看到我们为查找所有匹配关键字而构建的正则表达式替换。

      【讨论】:

      • words = ['cat', 'monk', 'dog'] your_list = ['caterpillar', 'dog', 'doggo', 'cat', 'monkey', 'doggy']我只需要从 your_list 中找到“猫”,但在搜索“猫”这个词时,“卡特彼勒”也会参与其中。
      • @Rick 不,这不会发生,因为我的正则表达式模式只搜索 \bcat\b,它不能匹配 catepillar
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多