我尝试使用Google Sheets正则表达式公式来获取给定字符串中连字符前面的所有数字的列表(比如在单元格A1
中):
=REGEXEXTRACT(A1, "\d-")
我的问题是它只返回第一个匹配项...*如何获取 * 所有匹配项 ?
范例文字:
"A1-Nutrition;A2-ActPhysiq;A2-BioMeta;A2-Patho-jour;A2-StgMrktg2;H2-Bioth2/EtudeCas;H2-Bioth2/Gemmo;H2-Bioth2/Oligo;H2-Bioth2/Opo;H2-Bioth2/Organo;H3-Endocrino;H3-Génétiq"
我的公式返回1-
,而我想得到1-2-2-2-2-2-2-2-2-2-3-3-
(作为数组或连接文本)。
我知道我可以使用脚本或其他函数(如SPLIT
)来实现所需的结果,但我真正想知道的是如何获得一个re 2正则表达式来返回“REGEX.*
“GoogleSheets公式中的多个匹配项。
我也尝试过用REGEXREPLACE
删除不需要的文本,但也没有成功(我无法删除连字符之前的其他数字)。
任何帮助都很感激!谢谢:)
7条答案
按热度按时间oknwwptz1#
实际上,您可以使用regexreplace在单个公式中完成此操作,用捕获组将所有值括起来,而不是替换文本:
基本上,它所做的就是用一个“捕获组”包围
\d-
的所有示例,然后使用regex extract,它会整洁地返回所有捕获。如果你想将其连接回一个字符串,你可以使用join将其打包回一个单元格:nxowjjhe2#
您可以在脚本编辑器中创建自己的自定义函数:
或者,如果需要返回用分隔符连接的单个单元格中的所有匹配项:
那么,就叫它
=ExtractAllRegex(A1, "\d-", 0, ", ")
吧。说明:
input
-当前单元格值pattern
-正则表达式模式groupId
-捕获要提取的组IDseparator
-用于连接匹配结果的文本。anauzrmj3#
编辑
我想出了更一般的解决办法:
=regexreplace(A1,"(.)?(\d-)|(.)","$2")
它只使用第二组匹配项
$2
替换除第二组匹配项(\d-)
之外的任何文本。学习正则表达式:https://regexone.com
试试这个公式:
=regexreplace(regexreplace(A1,"[^\-0-9]",""),"(\d-)|(.)","$1")
它将像这样处理字符串:
"A1-Nutrition;A2-ActPhysiq;A2-BioM---eta;A2-PH3-Généti***566*9q"
输出为:
1-2-2-2-3-
gev0vcfq4#
我无法获得适用于我的案例的公认答案。我想这样做,但需要一个快速的解决方案,并使用以下方法:
输入:
预期输出:
公式:
t0ybt7op5#
这似乎是工作,我已经试图验证它。
逻辑是
(1)将连字符后面的字母替换为空
(2)将后面没有连字符的任何数字替换为空
(3)将数字或勒胡号以外的所有项目取代为空白
测试结果
分析
我不得不按程序逐步检查这些选项,以使自己相信这是正确的。根据this reference,当存在由管道符号分隔的替代选项时,正则表达式应该按照从左到右的顺序匹配它们。除非规则1优先,否则上面的公式不能正常工作(否则,在规则(1)生效之前,它会将除数字或连字符之外的所有字符减少为空,并且您会从“Patho-jour”中获得一个额外的连字符)。
这里有一些我认为它必须如何处理文本的例子
p4rjhz4m6#
使用RegexReplace捕获组,然后执行RegexExctract的解决方案在这里也有效,但有一个陷阱。
=join(“",正则表达式提取(A1,正则表达式替换(A1,"(\d-)","($1)”)))
如果您试图获取值的单元格包含特殊字符,如括号“(“或问号“?”,则提供的解决方案将不起作用。
在我的例子中,我试图列出单元格中包含的所有“变量文本”。这些“变量文本“是这样写在里面的:“{example_name}"。但是单元格的全部内容都有特殊字符,使得regex公式确实中断。当我删除这些特殊字符时,我就可以像解决方案一样列出所有捕获的组。
flvtvl507#
有两种通用('Excel' / 'native' /非应用程序脚本)解决方案返回
REGEXEXTRACT
样式的正则表达式匹配数组:方法1)
在匹配项周围插入分隔符,删除垃圾,并调用
SPLIT
正则表达式的工作方式是从左到右迭代字符串,然后“消耗”。如果我们小心地消耗垃圾值,我们可以把它们扔掉。
(This绕过了当前公认的解决方案所面临的问题,即正如卡洛斯Eduardo Oliveira所提到的,如果语料库文本包含特殊的正则表达式字符,则它显然会失败。)
首先,我们选择一个分隔符,这个分隔符必须不存在于文本中。正确的方法是解析文本,用一个“临时分隔符”临时替换我们的分隔符,就像如果我们要使用逗号
","
,我们首先用"<<QUOTED-COMMA>>"
之类的字符替换所有现有的逗号,然后再取消替换它们。但是,为了简单起见,我们将从专用的unicode块中抓取一个随机字符(如
),并将其用作特殊的分隔符(注意,它是2个字节...... google电子表格可能不会以一致的方式计算字素中的字节数,但我们稍后会注意)。我们只需要使用lambda来定义temp=“match 1 match 2 match 3 ",然后使用它来移除最后一个分隔符,使其成为“match 1 match 2 match 3”,然后
SPLIT
它。取结果的
COLUMNS
将证明返回了正确的结果,即{" ", " ", " "}
。这是一个非常好的函数,可以转换为命名函数,并将其命名为
REGEXGLOBALEXTRACT(text,regex)
或REGEXALLEXTRACT(text,regex)
,例如:方法2)
使用递归
使用
LAMBDA
(也就是让你像其他编程语言一样定义一个函数),你可以使用一些来自lambda演算和函数编程的技巧:定义一个递归函数是一件令人困惑的事情,因为它没有一个简单的方法来引用它自己,所以你必须使用一个技巧/约定:递归函数技巧:* 要真正定义一个需要引用本身的函数f,请改为定义一个接受参数
itself
并返回实际所需函数的函数 *;把这个“约定”传递给Y组合子,把它变成一个实际的递归函数这种函数的管道称为Y-组合子。如果你有一些编程背景,这里有一个good article to understand it。
例如,要得到5!的结果(5阶乘,即实现我们自己的
FACT(5)
),我们可以定义:命名函数
Y(f)
=LAMBDA(f, (LAMBDA(x,x(x)))( LAMBDA(x, f(LAMBDA(y, x(x)(y)))) ) )
(这是Y-组合子,很神奇;您不必了解它就可以使用它)命名函数
MY_FACTORIAL(n)
=MY_FACTORIAL(5)
结果:120Y-组合子使得编写递归函数看起来相对容易,就像是编程类的入门。我使用命名函数是为了清晰起见,但你可以以牺牲理智为代价将它们全部丢弃...
这是如何应用到手头的问题?好的递归解决方案如下:
在下面的伪代码中,我使用'function'代替
LAMBDA
,但它们是一样的:不幸的是,递归方法是二次增长(因为它会一遍又一遍地将结果追加到自身,同时用越来越小的字节重新创建巨大的搜索字符串,所以1+2+3+4+5+...= big^2,这可能会增加很多时间),所以如果你有很多匹配,速度可能会很慢。为了提高速度,最好留在正则表达式引擎中,因为它可能是高度优化的。
当然,如果你想在表达式中使用varName,你可以通过与
LAMBDA(varName, expr)(varValue)
进行临时绑定来避免使用命名函数。(你可以将这种模式定义为命名函数=cont(varValue)
,以反转参数的顺序,使代码更简洁,或者不这样做。)varName = varValue
时,请改为这样写。ISNA(...)
它看起来像这样:
命名函数
allMatches(resultsToReturn, text, regex)
:未测试: