使用RegEx查找无序单词

时间:2018-12-22 21:06:57

标签: python regex

我想使用RegEx在以任何顺序出现一组单词的字符串中查找第一个序列。

例如,如果要查找单词hellomyworld,则:

  • 对于hello my sweet world,表达式将与hello my sweet world匹配;
  • 对于oh my, hello world,它将与my, hello world相匹配;
  • 对于oh my world, hello world,它将与my world, hello相匹配;
  • 对于hello world,没有匹配项。

经过研究,我尝试了表达式(?=.*?\bhello\b)(?=.*?\bmy\b)(?=.*?\bworld\b).*,它不能解决我的问题,因为如果所有单词都存在,它会匹配整个字符串,例如:

  • 对于oh my world, hello world,它与oh my world, hello world匹配

实现我所描述的内容合适的表达方式是什么?

(尽管RegEx是我的程序的首选方法,但是如果您认为不可行,欢迎使用其他任何python解决方案。)

2 个答案:

答案 0 :(得分:2)

通过使用Pattern.finditer()函数和Set对象的

统一迭代 pythonic 方法:

import re

test_str = '''The introduction here for our novel. 
Oh, hello my friend. This world is full of beauty and mystery, let's say hello to universe ...'''

words_set = {'my', 'hello', 'world'}    # a set of search words
words_set_copy = set(words_set)
pat = re.compile(r'\b(my|hello|world)\b', re.I)
start_pos = None
first_sequence = ''

for m in pat.finditer(test_str):        
    if start_pos is None:
        start_pos = m.start()           # start position of the 1st match object
    words_set_copy.discard(m.group())   # discard found unique match 

    if not words_set_copy:              # all the search words found
        first_sequence += test_str[start_pos: m.end()]
        break

print(first_sequence)

输出:

hello my friend. This world

您可以将上述方法转换为可重用的函数。

答案 1 :(得分:1)

我认为最好通过某种编程逻辑来完成此任务,而正则表达式将不容易且高效。但这是一个正则表达式,似乎在做您的工作,并且不管您是否在重复单词(您好,我的世界),

\b(hello|my|world)\b.*?((?!\1)\b(?:hello|my|world)\b).*?(?:(?!\1)(?!\2)\b(?:hello|my|world)\b)

这里的想法是

  1. 创建一个备用组\b(hello|my|world)\b并将其放入组1
  2. 然后可选地,它后面可以有零个或多个任何字符。
  3. 然后必须在其余两个单词中的任何一个后面,而不是在第一组中匹配的单词,这就是为什么我使用((?!\1)\b(?:hello|my|world)\b)并将第二个匹配项放在第二组的原因。
  4. 然后,它后面可以有零个或多个任何字符。
  5. 然后再次应用相同的逻辑,其中第三个单词应该是group1或group2中未捕获的单词,因此此正则表达式(?:(?!\1)(?!\2)\b(?:hello|my|world)\b)

Here is a Demo