在 python 中查找完全匹配词的索引

finding indices of exact match words in python

我正在尝试查找句子中模式的索引。模式可以是一个词或词的组合。我为此使用了正则表达式。但我有一些边缘情况需要处理。

import re

word = "is"
s = "Is (valid) is (valid), is-not (not valid), is. (valid) is!, (valid), is_1 (not valid) ,is (valid), is? (valid)"

iters = re.finditer(r"\b" + re.escape(word) + r"\b", s, re.I)
indices = [m.start(0) for m in iters]
print(indices)

这输出

[0, 11, 23, 43, 55, 87, 99]

如您所见,is 与某些符号的出现是必需的匹配项,而有些则不是。这是可以考虑用于匹配的有效符号列表。

[" ", ",", ".", "!", "?"]

如何避免结果中的第 3 个匹配项 (is-not)?

如果您之后搜索所有“不是”,您可以检查哪些值在一个中,但在另一个中没有。

indices_is = [m.start(0) for m in iters_is]

然后你 运行 再次输入该代码并得到

indices_isnot = [m.start(0) for m in iters_isnot]

真实的是列表:

indices_is = [i for i in indeces_is if i not in indices_isnot]

如果您能够清楚地定义不允许的字界字符(在您提供的示例中,它只会是破折号字符(-)),那么一个简单的、仅正则表达式的解决方案可能涉及否定 lookbehind and negative lookahead:

的概念
pattern = r"(?<!-)\b" + re.escape(word) + r"\b(?!-)"

这个正则表达式背后的想法是匹配被单词边界包围的单词的每个实例(正如您已经在做的那样)除非单词前面或后面有破折号。您还可以考虑使用正向后视和前视,即不是定义不允许的字符列表,而是定义允许在模式之前或之后的字符列表。我提到这一点是因为您在问题中提供了允许的字符列表;但是,由于 lookbehind/lookahead.

的限制,我不知道使用这种方法的解决方案也考虑了单词在行的开头或结尾的可能性

你的问题有点模棱两可,因为你将一些特定字符指定为边界字符(而不是任何非单词字符作为边界字符),但你在你的中使用了“\b”单词边界断言代码(使用任何非单词字符作为边界字符)。因此,我无法确定您是否只是想调整“\b”以不将“-”视为边界字符,或者您是否想重写正则表达式以完全使用问题中指定的边界字符。

要调整“\b”以忽略“-”作为边界字符,您可以使用否定后向断言和否定先行断言(基本上说,“除非边界是由破折号字符引起的”)所以只有一行代码会改变:

    iters = re.finditer(r"(?<!-)\b" + re.escape(word) + r"\b(?!-)", s, re.I)

此更改导致输出变为

    [0, 11, 43, 55, 87, 99]

这似乎是你想要的。请记住,还有其他非单词字符(除了您提到的字符之外)会导致正则表达式匹配(在通用字符串中,与您提供的字符串相反)。

我现在不打算提供正则表达式来处理您指定的字符,因为您的示例代码使用了“\b”,这意味着您想要使用它,但不要将“-”视为一个边界字符(因此也意味着您列出的边界字符主要来自您的示例,并且没有使列表包含所有内容)。