Table of contents
在本教程中,我们将深入了解如何在Excel中使用regex来匹配字符串。
当你需要在一个单元格范围内找到某个值时,你会使用MATCH或XMATCH函数。 当在一个单元格中寻找一个特定的字符串时,FIND和SEARCH函数就会派上用场。 那么你如何知道一个单元格中是否包含与给定模式相匹配的信息呢? 很明显,通过使用正则表达式。 但开箱后Excel并不支持正则表达式!不用担心,我们会强制它支持。)
Excel VBA的Regex函数来匹配字符串
从标题就可以看出,为了在Excel中使用正则表达式,你需要创建自己的函数。 幸运的是,Excel的VBA有一个内置的 正则 对象,你可以在你的代码中使用它,如下所示。
Public Function RegExpMatch(input_range As Range, pattern As String , Optional match_case As Boolean = True ) As Variant Dim arRes() As Variant 'array to store the results Dim iInputCurRow, iInputCurCol, cntInputRows, cntInputCols As Long 'index of current row in the source range, index of current column in the source range, count of rows, count of columns On Error GoTo ErrHandlRegExpMatch = arRes Set regex = CreateObject ( "VBScript.RegExp" ) regex.pattern = pattern regex.Global = True regex.MultiLine = True If True = match_case Then regex.ignorecase = False Else regex.ignorecase = True End If cntInputRows = input_range.Rows.Count cntInputCols = input_range.Columns.Count ReDim arRes(1 To cntInputRows, 1 To cntInputCols) For iInputCurRow = 1 to cntInputRows ForiInputCurCol = 1 To cntInputCols arRes(iInputCurRow, iInputCurCol) = regex.Test(input_range.Cells(iInputCurRow, iInputCurCol).Value) Next Next RegExpMatch = arRes Exit Function ErrHandl: RegExpMatch = CVErr(xlErrValue) End Function在VBA编辑器中粘贴该代码,你的新的 正则匹配 如果你对VBA不是很有经验,这个指南可能会有帮助:如何在Excel中插入VBA代码。
注意:在插入代码后,记得将你的文件保存为 支持宏的工作簿 (.xlsm)。
正则匹配语法
ǞǞǞ 正则匹配 函数检查源字符串的任何部分是否与正则表达式相匹配。 结果是一个布尔值:如果发现至少一个匹配,则为TRUE,否则为FALSE。
我们的自定义函数有3个参数--前两个是必须的,最后一个是可选的。
RegExpMatch(text, pattern, [match_case])在哪里?
- 文本 (required) - 一个或多个要搜索的字符串。 可以作为一个单元格或区域参考提供。
- 样式 (required) - 要匹配的正则表达式。 当直接放在公式中时,模式必须用双引号括起来。
- Match_case (可选) - 定义匹配类型。 如果为 "true "或省略(默认),则进行大小写敏感的匹配;如果为 "false",则不区分大小写。
该功能可在所有版本的Excel 365、Excel 2021、Excel 2019、Excel 2016、Excel 2013和Excel 2010中使用。
关于RegExpMatch你应该知道的3件事
在我们进行实际计算之前,请注意以下几点,以澄清一些技术问题。
- 该函数可以处理一个 单细胞 或 细胞的范围 在后一种情况下,结果以动态数组或溢出范围的形式返回到邻近的单元格,如本例所示。
- 在默认情况下,该函数是 区分大小写 要忽略文本的大小写,请设置 match_case 由于VBA Regexp的限制,不支持不区分大小写的模式(?i)。
- 如果没有找到一个有效的模式,该函数返回FALSE;如果 模式是无效的 ,发生#VALUE!错误。
下面,你会发现一些为演示目的而创建的regex匹配例子。 我们不能保证我们的模式在你的真实工作表中的更大范围的输入数据中能无误地工作。 在投入生产之前,一定要根据你的需要测试和调整我们的样本模式。
如何在Excel中使用regex来匹配字符串
当你想匹配的所有字符串具有相同的模式时,正则表达式是一个理想的解决方案。
假设你有一个单元格范围(A5:A9),包含一些物品的各种细节。 你想知道哪些单元格有SKU。 假设每个SKU由2个大写字母、1个连字符和3个数字组成,你可以用以下表达式来匹配它们。
样式 : b[A-Z]{2}-d{3}\b
其中[A-Z]{2}表示从A到Z的任何2个大写字母,\d{3}表示从0到9的任何3个数字。 \b字符表示单词边界,意味着SKU是一个独立的单词,而不是一个更大的字符串的一部分,如23-MAR-2022。
确定了模式,我们就可以继续写公式了。 从本质上讲,使用自定义函数与本机函数没有什么不同。 只要你开始输入公式,函数的名称就会出现在Excel的自动完成功能建议的列表中。 然而,在动态阵列Excel(Microsoft 365和Excel 2021)和传统Excel(2019和旧版本)中有一些细微差别。
匹配一个单元格中的字符串
要匹配单个单元格中的字符串,请在第一个参数中提及该单元格。 第二个参数应该包含一个正则表达式。
=RegExpMatch(A5, "\b[A-Z]{2}-\d{3}\b")
图案也可以保存在预定义的单元格中,用绝对引用($A$2)锁定。
=RegExpMatch(A5, $A$2)
在第一个单元格中输入公式后,你可以把它向下拖到所有其他行中。
这种方法在以下情况下效果很好 所有Excel版本 .
一次性匹配多个单元格中的字符串
要用一个公式匹配多个字符串,在第一个参数中包括一个范围参考。
=RegExpMatch(A5:A9, "\b[A-Z]{2}-\d{3}\b")
在 Excel 365 和 Excel 2021 支持动态数组,它是这样工作的--你在第一个单元格中输入公式,点击回车,公式就会自动溢出到下面的单元格。
在 Excel 2019年 和更早的版本,它只能作为一个传统的CSE数组公式工作,在一个单元格范围内输入,并通过同时按下Ctrl + Shift + Enter键完成。
匹配数字的Regex
要匹配从0到9的任何单一数字,使用 \d 根据你的特定任务,添加一个合适的量词或创建一个更复杂的模式。
匹配任何数字的Regex
要匹配任何长度的数字,请在/d字符后面加上+量词,这表示要寻找包含1位或更多数字的数字。
样式 : \d+
=RegExpMatch(A5:A9, "\d+")
匹配特定长度的数字的Regex
如果你的目标是匹配含有一定数字的数值,那么就使用\d和一个适当的量词。
例如,为了匹配正好由7位数字组成的发票号码,你会使用\d{7}。 然而,请记住,它将匹配字符串中任何地方的7位数字,包括10位或100位数字。 如果这不是你正在寻找的,把字的边界\b放在两边。
样式 :: \b\d{7}\b
=RegExpMatch(A5:A9, "\b\d{7}\b")
匹配电话号码的Regex
由于电话号码可以用不同的格式书写,匹配它们需要一个更复杂的正则表达式。
在下面的数据集中,我们将搜索前两组有3位数字,最后一组有4位数字的10位数字。 这些组可以用句号、连字符或空格隔开。 第一组可以用括号括起来,也可以不用。
模式:((d{3}\))
对这个正则表达式进行分解,我们得到的结果如下。
- 第一部分((d{3}\)\)。
- [-\.\s]? 部分表示0或1次出现在方括号中的任何字符:连字符、句号或空白处。
- 接下来,还有一组3个数字d{3},后面是任何连字符、句号或空白[\-/.\s]? 出现0次或1次。
- 最后一组4个数字 \d{4}后面有一个词的边界 \b,以表明一个电话号码不能成为一个更大数字的一部分。
在A5中的原始字符串和A2中的正则表达式中,公式的形式如下。
=RegExpMatch(A5, $A$2)
...并且完全按照预期工作。
注意事项。
- 没有检查国际代码,所以它们可能存在也可能不存在。
- 在正则表达式中,\s代表任何空白字符,如空格、制表符、回车符或新行。 要只允许空格,请使用[-\.]而不是[-\.\s]。
- [^13] 将匹配任何非1或3的单一字符。
- [^1-3]将匹配任何非1、2或3的单个字符(即1至3的任何数字)。
- 上述重词只适用于 单线 如果是小行字符串,^和$字符匹配的是每一行的开头和结尾,而不是输入字符串的开头和结尾,因此,重构词只在第一行搜索。
- 要匹配的字符串是 不要启动 有一定的文字 ,使用正则表达式,如^(?!!lemons).*$
- 要匹配的字符串是 不要结束 有一定的文字 ,将尾部字符串锚列入搜索模式:^(((?!lemons$). )*$
- 帐号 考虑到\w可以匹配任何字母、数字或下划线,我们可以得到以下词组:[\w\.\-]+。
- 域名 可以包括大写和小写字母、数字、连字符(但不在第一个或最后一个位置)和点(在子域的情况下)。 由于不允许使用下划线,我们使用3个不同的字符集来代替\w:[A-Za-z0-9]+[A-Za-z0-9\.\-]*[A-Za-z0-9]+
- 顶级域名 由一个点和大、小写字母组成。 它可以包含2至24个字母(目前最长的顶级域名):[A-Za-z]{2,24}。
- 为 RegExpMatch 提供一个范围引用,因此它返回一个 TRUE 和 FALSE 值的数组。
- 使用双重否定(--)将逻辑值胁迫为1和0。
- 获取SUM函数,将所得数组中的1和0相加。
- 关于 阿博比特数据 选项卡,在 文本 组,点击 Regex工具 .
- 关于 Regex工具 窗格,执行以下操作。
- 选择源字符串。
- 输入你的图案。
- 选择 匹配 选择。
- 要使结果成为公式,而不是数值,请选择 作为一个公式插入 复选框。
- 点击 匹配 按钮。
- 该功能可以是 插入式的 直接在一个细胞中 通过标准 插入功能 对话框中,它被归类为 AblebitsUDFs .
- 默认情况下,正则表达式被添加到公式中,但你也可以把它放在一个单独的单元格中。 为此,只需在第2个参数中使用一个单元格参考。
- 在默认情况下,该函数是 区分大小写 对于不区分大小写的匹配,使用(?i)模式。
不匹配字符的Regex
要找到不包含某个字符的字符串,可以使用否定的字符类[^]来匹配不在括号内的任何内容。 例如:。
在一个电话号码列表中,假设你想找到那些没有国家代码的电话号码。 记住,任何国际代码都包括+号,你可以使用[^\+]字符类来寻找不包含加号的字符串。 重要的是要意识到,上述表达式匹配任何不是+的单一字符。 因为电话号码可以在字符串的任何地方,而不是在最开始的时候,必须添加*量词来检查每个后续的字符。 开始的^和结束的$锚确保整个字符串被处理。 结果,我们得到下面的正则表达式,说 "不要在字符串的任何位置匹配+字符"。
样式 : ^[^\+]*$
=RegExpMatch(A5, "^[^\+]*$")
不匹配字符串的Regex
虽然没有特殊的正则表达式语法用于不匹配特定的字符串,但你可以通过使用负数的lookahead来模拟这种行为。
假设你希望找到以下的字符串 不含 这个正则表达式会起到很好的作用。
样式 : ^((?!柠檬).)*$
显然,这里需要做一些解释。 负向查找(?!lemons)向右看,看前面是否有 "lemons "这个词。 如果 "lemons "不在那里,那么点号就会匹配除换行之外的任何字符。 上述表达式只进行了一次检查,*量词重复了零次或多次,从^锚定的字符串的开始到^锚定的字符串的结束。$.
为了忽略文本大小写,我们将第3个参数设置为FALSE,使我们的函数不区分大小写。
=RegExpMatch(A5, $A$2, FALSE)
提示和说明。
不区分大小写的匹配
在经典的正则表达式中,有一个特殊的模式用于不区分大小写的匹配(?i),这在VBA RegExp中是不支持的。 match_case 要进行不区分大小写的匹配,只需将其设置为FALSE。
比方说,你希望识别日期,如1-3-22或01-MAR-2022。 为了匹配 dd-mmm-yyy 和 d-mmm-yy 格式,我们使用的是以下正则表达式。
样式 ::b\d{1,2}-(Jan
我们的表达式搜索的是一组1或2位数字,后面是连字符,后面是任何一个月份的缩写,中间用
为什么不使用更简单的模式,如:\d{1,2}-[A-Za-z]{3}-\d{2,4}\b? 为了防止像01-ABC-2020这样的错误匹配。
在A2中输入图案,你会得到以下公式。
=RegExpMatch(A5, $A$2, FALSE)
匹配有效电子邮件地址的Regex
众所周知,电子邮件地址由4部分组成:用户名、@符号、域名(邮件服务器)和顶级域名(如.com、.edu、.org等)。 为了检查电子邮件地址的有效性,我们需要使用正则表达式来复制上述结构。
样式 : \b[\w\.\-]+@[A-Za-z0-9]+[A-Za-z0-9\.\-]*[A-Za-z0-9]+\.[A-Za-z]{2,24}\b
为了更好地理解这里发生了什么,让我们仔细看看每个部分。
注意:该模式假定域名包含2个或更多的字母数字字符。
原文在A5,图案在A5,公式是这样的。
=RegExpMatch(A5, $A$2)
或者你可以使用一个更简单的正则表达式进行电子邮件验证,使用小写或大写字符集。
样式 : \b[\w\.\-]+@[a-z0-9]+[a-z0-9\.\-]*[a-z0-9]+\.[a-z]{2,24}\b
但要让你的公式不区分大小写。
=RegExpMatch(A5, $A$2, FALSE)
Excel的IF公式与匹配的重名词
由于内置函数和自定义函数相处得很好,没有什么能阻止你在一个公式中同时使用它们。
为了在正则表达式被匹配时返回或计算一些东西,而在不匹配时返回或计算一些其他东西,在 IF 的逻辑文本中嵌入自定义 RegExpMatch 函数。
IF(RegExpMatch(...), [value_if_true], [value_if_false])例如,如果A5中的一个字符串包含一个有效的电子邮件地址,你可以返回 "是";否则返回 "否"。
=IF(RegExpMatch(A5, $A$2,), "是", "否")
如果搜索结果与之匹配,则计数。
由于原生的Excel函数不支持正则表达式,因此不可能直接在COUNTIS或COUNTIFS函数中放入一个反义词。 幸运的是,你可以使用我们的自定义函数来模拟这个功能。
假设你用一个词组来匹配电话号码,并将结果输出到B列。 要想知道有多少单元格包含电话号码,你只需要计算B5:B9中的TRUE值。 这可以用标准的COUNTIF公式轻松完成。
=countif(b5:b9, true)
你不想在你的工作表中有任何额外的列吗? 没问题。 考虑到我们的自定义函数可以一次处理多个单元格,而Excel的SUM可以将数组中的数值相加,你可以这样做。
=SUM(-RegExpMatch(A5:A9, $A$2))
用Ultimate Suite进行Regex匹配
我们的终极套件的用户可以利用四个强大的Regex函数,而不需要在他们的工作簿中添加任何VBA代码,因为它们在插件安装过程中被顺利地集成到Excel中。 我们的自定义函数由标准的.NET RegEx引擎处理,支持全功能的经典正则表达式。
如何使用自定义RegexMatch函数
假设你安装了最新版本的Ultimate Suite(2021.4或更高版本),你可以通过两个简单的步骤创建一个Regex Match公式。
一会儿后, AblebitsRegexMatch 函数被插入到你的数据右边的一个新列中。
在下面的截图中,该函数检查A列中的字符串是否包含7位数的数字。
提示。
欲了解更多信息,请参见AblebitsRegexMatch函数。
这就是如何在Excel中进行正则表达式匹配的方法。 感谢你的阅读,并期待下周在我们的博客上见到你!
可用的下载
Excel Regex匹配示例(.xlsm文件)。
终极套房14天全功能版(.exe文件)