使用正则表达式匹配查找所有包含多个单词的字符串单元格。

3
我正在使用ArrayFormula和FILTER组合来列出包含所有搜索术语单词的列中的所有单元格。我使用REGEXMATCH而不是QUERY / CONTAINS / LIKE,因为我的FILTER具有其他返回TRUE / FALSE的标准。我的问题似乎是优先级。因此以下正则表达式在有限的情况下有效。
=ArrayFormula(filter(A1:A5,regexmatch(A1:A5,"(?i)^"&"(.*?\bbob\b)(.*?\bcat\b)"&".*$")))

如果Bob在cat之前,它将找到Bob和cat。

如果我尝试使用前瞻?=,即Google表格失败。

=ArrayFormula(filter(A1:A5,regexmatch(A1:A5,"(?i)^"&"(?=.*?\bbob\b)(?=.*?\bcat\b)"&".*$")))

我不想在字符串中使用 '|' 替换(重复和反转),因为输入的单词可能超过两个,这样替换会变得指数级别复杂。
以下是测试搜索数组(每行都包含一个字符串的单元格)...
Bob ate the dead cat
The cat ate live bob
No cat ate live dog
Bob is dead
Bob and the cat are alive

...以及我想要的预期结果。

Bob ate the dead cat
The cat ate live bob
Bob and the cat are alive

一旦我整理好了正则表达式,最终的解决方案将是一个用户输入文本框,他们只需输入必须在字符串中找到的单词,例如 'Bob cat'。我认为我可以将这个输入字符串拆分成单独的单词,并将它们连接到上面的表达式中,然而,如果有一种'最佳实践'的方法来完成这个任务,我想听听。


1
RE2 引擎不支持无需消耗文本即可检查模式的前瞻。因此,唯一的解决方法是使用多个匹配函数:and(regexmatch(A1:A5,'(?i)\bBob\b'), regexmatch(A1:A5, '(?i)\bcat\b')) - Wiktor Stribiżew
3个回答

5

查找2个字符串

尝试:

=FILTER(A:A,REGEXMATCH(A:A,"(?i)bob.*cat|cat.*bob"))

您不需要使用ArrayFormula,因为filter本身就是一个数组公式。

  • (?i) - 使搜索不区分大小写
  • bob.*cat|cat.*bob - 匹配"bob → cat"或"cat → bob"

查找多个字符串

如果要匹配多个单词,则需要使用更复杂的公式。

假设我们在A列中有一个列表:

Bob ate the dead cat
The cat ate live bob
No cat ate live dog
Bob is dead
Bob and the cat are alive
Cat is Bob
ate Cat bob

需要查找所有三个单词的匹配项,并将它们放入C列:

cat
ate
bob

公式如下: =FILTER(A:A,MMULT(--REGEXMATCH(A:A, "(?i)"&TRANSPOSE(C1:C3)),ROW(INDIRECT("a1:a"&COUNTA(C1:C3)))^0)=COUNTA(C1:C3)) 它使用了 RegexMatch 函数以及单词列表 C1:C3 的转置,然后 mmult 函数将匹配项相加,并用 =COUNTA(C1:C3) 比较匹配数与列表中单词数的数量。
结果如下:
Bob ate the dead cat
The cat ate live bob
ate Cat bob

乍一看,“多个字符串”似乎是完美的解决方案。非常感谢Max。现在我需要花些时间来理解如何将其完全整合到实际任务中。无论如何,我已经预先将“最佳答案”给了你。 - DeeKay789

1
请看这个是否符合您的要求。在B1单元格输入以下内容:
=arrayformula(filter(A1:A5,regexmatch(A1:A5,lower(index(split(C2," "),0,1)))*regexmatch(lower(A1:A5),lower(index(split(C2," "),0,2)))))

在C2中输入您的搜索词,它们之间需要用空格隔开(例如:cat Bob)。
所有单词都会被转换为小写。索引拆分将单词分隔在C2中,分隔的单词将进入regexmatch。下面是我的共享测试电子表格:

https://docs.google.com/spreadsheets/d/1sDNnSeqHbi0vLosxhyr8t8KXa3MzWC_WJ26eSVNnG80/edit?usp=sharing

扩展Max的非常好的答案,这将更改列C中单词列表的公式。我在共享电子表格(Sheet2)中添加了一个示例。
=FILTER(A:A,MMULT(--REGEXMATCH(A:A,"(?i)"&TRANSPOSE(INDIRECT( "C1:C" & counta(C1:C ) ))),ROW(INDIRECT("a1:a"&COUNTA(INDIRECT( "C1:C" & counta(C1:C ) ))))^0)=COUNTA(INDIRECT( "C1:C" & counta(C1:C ) )))

两位回答者的答案都适用于给定的数据,非常感谢。我必须解析和拆分数据,以便使用在更大的计划中。那么,在每个“条件”实例之前,'=COUNTA(SPLIT(C2,“ ”)是否是提供if语句的有效方法? - DeeKay789

0

或许更容易理解一些(我讨厌 MMULT)

=query({A1:A},"select Col1 where "&join(" and ",arrayformula("Col1 匹配 '."&filter(B:B,B:B<>"")&".'")))

其中 A 包含您的短语列表,B 包含您的条件词。

这个公式的一部分,=join(" and ",arrayformula("Col1 匹配 '."&filter(D3:D,D3:D<>"")&".'")) 从 B 中的术语构建查询字符串。例如:

Col1 匹配 '.cats.' and Col1 匹配 '.dogs.'

然后将此列表连接到整个“select”表达式中:

select Col1 where Col1 匹配 '.cats.' and Col1 匹配 '.dogs.'


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接