【问题标题】:Find unordered words with RegEx使用 RegEx 查找无序单词
【发布时间】:2018-12-22 21:06:57
【问题描述】:

我想使用 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 解决方案。)

【问题讨论】:

  • 你为什么要一个正则表达式来解决这个任务?
  • @YassinHajaj 欢迎提出其他建议,尽管在我正在处理的程序中干净地安装正则表达式会更容易,因为我已经以相同的方法将正则表达式用于其他搜索任务
  • @CertainPerformance python,将编辑
  • 如果不允许重复模式,请尝试this。您需要的是在每个成功匹配的第一个捕获组中。
  • 如果regex 模块支持对相关捕获组的引用,您可以使用this too

标签: python regex


【解决方案1】:

使用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

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

【讨论】:

  • 这个超级聪明,不错。您介意将 re.I 解释为 re.compile 中的第二个参数吗?
  • @Datanovice,欢迎,re.Ire.IGNORECASE 选项的快捷方式
【解决方案2】:

我认为这项任务最好通过一些编程逻辑来完成,而正则表达式不会简单有效。但这里有一个正则表达式,它似乎在做你的工作,不管你是否有重复的词(你好,我的世界),

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

这里的想法是,

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

Here is a Demo

【讨论】:

  • 这看起来很完美!经过一些测试后会检查它是否正确。非常感谢。
  • 觉得你可能会觉得这很有趣:我在这里为我的项目制作了一个程序,它可以用可变词生成该表达式:pyfiddle.io/fiddle/03bfbfa3-53f3-437a-a7dc-ce9630e3a46d/?i=true
  • @JocaPinto:这很好。是的,正则表达式非常系统和合乎逻辑,可以通过代码生成它,你做到了:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-10
  • 1970-01-01
  • 2015-09-04
  • 2020-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多