首页 > 解决方案 > 使用 Python 进行组合词匹配的正则表达式

问题描述

尝试在给定文本中查找多个单词匹配。例如:

text = "oracle sql"
regex = "(oracle\\ sql|sql)"
re.findall(regex,text,re.I)

实际输出

甲骨文

预期产出

甲骨文 sql,sql

谁能告诉我,正则表达式的问题在哪里?

更新:

@jim 如果出现多个重叠,它将不起作用,例如:

re.findall("(?=(spark|spark sql|sql))","spark sql",re.I)

实际输出

['火花','sql']

预期输出:

['spark','sql','spark sql']]

注意:在上述情况下,如果两者都匹配,则不会匹配单词组合。

更新 :

检查链接:repl.it/repls/NewFaithfulMath

标签: pythonregex

解决方案


您不需要转义空格。

import re
text = "oracle sql"
regex = "(oracle sql|sql)"
print re.findall(regex, text, re.I)

文档

返回字符串中模式的所有非重叠匹配,作为字符串列表。

这算作重叠匹配。

返回重叠匹配

您可以使用前瞻来捕获您正在寻找的字符串,但因为它在技术上与前瞻匹配,所以它们不会重叠。

import re
text = "oracle sql"
regex = "(?=(oracle sql|sql))"
print re.findall(regex, text, re.I)

输出:

['oracle sql', 'sql']

看到它在行动

这种实现的缺点是它只会在字符串中的特定位置为每个单词找到 1 个匹配项。这是由于重叠匹配。

例如(my test|my|test)只会找到['my test', 'test'].

您总是可以使用正则表达式替换,它也会找到重叠匹配,例如regex,但这仍然只能找到['my test', 'test']pattern (my test|my|test)

import regex as re
text = "oracle sql"
regex = "(oracle sql|sql)"
print re.findall(regex, text, re.I, overlapped=True)

递归

正则表达式只会为每个字符找到一个匹配项。它已经根据“oracle sql”找到了第一个字符的匹配项,因此您无法仅在oracle. 你找不到每一个。

但是......您可以使用递归函数尝试将相同的字符串与所有项目匹配 - 已经匹配的项目。

我不确定这段代码的性能如何,因为你可以执行很多正则表达式搜索。

import re

def find_all_matches(text, items):
  regex_items = '|'.join(items)
  regex = "(?=({}))".format(regex_items)
  matches = re.findall(regex, text, re.I)
  new_items = [i for i in items if i not in matches]
  if new_items:
    new_matches = find_all_matches(text, new_items)
    return matches + new_matches
  return matches
print find_all_matches("oracle sql", ['oracle sql', 'oracle', 'sql'])

输出:

['oracle sql', 'sql', 'oracle']

没有正则表达式

最后,您可以在没有正则表达式的情况下实现这一点。我再一次没有看过这个的表现。

def find_all_matches(text, items):
  return [i for i in items if i in text]

print find_all_matches("oracle sql", ['oracle sql', 'oracle', 'sql'])

输出:

['oracle sql', 'oracle', 'sql']

推荐阅读