【问题标题】:Finding Arbitrarily Long Word Patterns using Regular Expression in Python在 Python 中使用正则表达式查找任意长的单词模式
【发布时间】:2017-02-28 18:57:07
【问题描述】:

我正在使用 Python 3.6 来查找文本中所有出现的“as”+单词+“as”,并且两边都有三个单词的上下文。

例如,如果我在上运行我的程序

"The dog was as wildly energetic as the old one. It was as bright as it has ever been."

理想的输出是

"The dog was as wildly energetic as the old one"
"one. It was as bright as it has ever"

这应该是一件容易的事,但我想不通。 (我对编程很陌生。)起初我尝试在文本的单词标记版本上执行此操作,但认为在原始字符串上使用正则表达式可能更容易。

我能想到的最好的方法是:

#FINDING __ AS __ AS __ PATTERNS

raw = "The dog was as wildly energetic as the old one. It was as bright as it has ever been."

import re

pattern_find = re.compile(r'\w* as \w* as \w*')    #Here we specify the regex code.

results = pattern_find.findall(raw)    #Here we do the search and put the results in a list.

print(results)

哪个输出

['was as bright as it']

完全忽略两次出现的“as”之间有两个单词的情况。这让我感到惊讶,因为我认为通过在\w 上包含星号*,它会捕获任意长的单词序列。 (似乎正在发生的事情是\w* 正在捕获任意长的连续字符字符串,而不是单词。)

我的问题是:

  1. 如何使用正则表达式得到我想要的?
  2. 有没有更好的方法来达到我想要的结果?

注意:我知道我可以使用 NLTK 的concordance() 来查找带有上下文的单个单词,但它不允许用户指定单词的模式。使用正则表达式的替代方法可能涉及从concordance() 构建一个函数。

【问题讨论】:

    标签: regex python-3.x nltk


    【解决方案1】:

    Regex 是适合这项工作的工具,尽管存在一些缺陷。您必须创建一个模式,最多捕获 3 个上下文单词,但如果没有 3 个单词,则更少。

    这个正则表达式应该可以解决问题:

    (?:\S+\s+){,3}\b[aA]s(?:\s+\S+)+?\s+as\b(?:\s+\S+){,3}
    

    解释:

    (?:\S+\s+){,3}  # match a word, followed by space(s). Up to 3 times.
    \b[aA]s         # assert word boundary and match "as"
    (?:\s+\S+)+?    # match any number of words, but as few as possible
    \s+             # followed by space(s)
    as\b            # and another "as"
    (?:\s+\S+){,3}  # match up to 3 more words
    

    【讨论】:

    • 谢谢!很好的解释,但你能解释一下?: 的功能,它开始正则表达式的单词匹配部分吗?跟命名组有关系吗?
    • @Silenus ?: 表示非捕获组。不过,在这种模式中并不重要,还不如使用普通的捕获组。只是一种习惯。
    【解决方案2】:

    \w 是单个单词字符,而不是整个单词。 \w* 确实会匹配一个单词(即连续的单词字符)。不过,您最好使用\w+ 来匹配单个单词字符或更多,而不是零单词字符或更多

    所以你可以尝试匹配多个单词:

    \w+ \w+ \w+ as \w+ as \w+ \w+ \w+

    或者使用实际出现次数:

    (\w+ ){3}as \w+ as (\w+ ){3}

    如果你不关心“as”之间有多少个单词,你可以匹配任意数量的出现:

    (\w+ ){3}as (\w+ )+as (\w+ ){3}

    更高级的方法是:

    (?:(?:\w+\s+)+as\s+){2}(?:\w+\s+)+

    【讨论】:

    • 感谢您的快速回答!您的“高级方式”似乎对我有用,但是当我插入您的其他正则表达式时,我没有得到任何输出。
    • 那是因为我没有省略表达式之间的空格。所以他们正在寻找“3次出现一些单词字符后跟一个空格”,然后是“一个空格后跟'as'”。会修复的。
    猜你喜欢
    • 1970-01-01
    • 2015-06-23
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2022-07-14
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    相关资源
    最近更新 更多