Regex提取Excel中的字符串(一个或所有匹配)。

  • Share This
Michael Brown

在本教程中,你将学习如何在Excel中使用正则表达式来查找和提取与给定模式相匹配的子串。

Microsoft Excel提供了一些从单元格中提取文本的函数。 这些函数可以应对工作表中大多数的字符串提取挑战。 大多数,但不是全部。 当文本函数出现问题时,正则表达式就会来拯救你。 等等,Excel没有RegEx函数!确实,没有内置的函数。 但没有什么可以阻止你使用自己的函数:)

    Excel VBA Regex函数提取字符串

    要在你的Excel中添加一个自定义的Regex提取函数,请在VBA编辑器中粘贴以下代码。 为了在VBA中启用正则表达式,我们使用了内置的Microsoft RegExp对象。

    Public Function RegExpExtract(text As String , pattern As String , Optional instance_num As Integer = 0, Optional match_case As Boolean = True ) Dim text_matches() As String Dim matches_index As Integer On Error GoTo ErrHandl RegExpExtract = "" Set regex = CreateObject ( "VBScript.RegExp" ) regex.pattern = pattern regex.Global = True regex.MultiLine = True If True = match_case Thenregex.ignorecase = False Else regex.ignorecase = True End If Set matches = regex.Execute(text) If 0 <matches.Count Then If (0 = instance_num) Then ReDim text_matches(matches.Count - 1, 0) For matches_index = 0 To matches.Count - 1 text_matches(match_index, 0) = matches.Item(match_index) Next matches_index RegExpExtract = text_matches Else RegExpExtract = matches.Item(instance_num - 1) EndIf End If 退出函数 ErrHandl: RegExpExtract = CVErr(xlErrValue) 结束函数

    如果你对VBA没有什么经验,一份逐步的用户指南可能会有帮助:如何在Excel中插入VBA代码。

    注意:为了使该功能发挥作用,请确保将你的文件保存为 支持宏的工作簿 (.xlsm)。

    正则Extract的语法

    ǞǞǞ 正则Extract 函数在输入字符串中搜索与正则表达式相匹配的值,并提取一个或所有匹配的值。

    该函数的语法如下。

    正则Extract(text, pattern, [instance_num], [match_case])

    在哪里?

    • 文本 (required) - 要搜索的文本字符串。
    • 样式 (required) - 要匹配的正则表达式。 当直接在公式中提供时,模式应该用双引号括起来。
    • Instance_num (可选) - 一个序列号,表示要提取的实例。 如果省略,则返回所有找到的匹配数据(默认)。
    • Match_case (可选) - 定义是否匹配或忽略文本大小写。 如果为 "true "或省略(默认),则进行区分大小写的匹配;如果为 "false "则不区分大小写。

    该功能可在所有版本的Excel 365、Excel 2021、Excel 2019、Excel 2016、Excel 2013和Excel 2010中使用。

    关于RegExpExtract你应该知道的4件事

    要在你的Excel中有效地使用这个函数,有几个重要的事项需要注意。

    1. 默认情况下,该函数返回 所有发现的匹配 要想获得一个特定的发生,可以给一个相应的数字到 实例_num 争论。
    2. 在默认情况下,该函数是 区分大小写 对于不区分大小写的匹配,可将 match_case 由于VBA的限制,不区分大小写的结构(?i)将无法工作。
    3. 如果一个 没有找到有效的模式 ,该函数不返回任何东西(空字符串)。
    4. 如果 模式是无效的 ,发生#VALUE!错误。

    在你开始在工作表中使用这个自定义函数之前,你需要了解它的能力,对吗? 下面的例子涵盖了一些常见的使用情况,并解释了为什么在动态阵列Excel(Microsoft 365和Excel 2021)和传统Excel(2019和旧版本)中行为可能不同。

    注意:外面的正则表达式例子是为简单的数据集编写的。 我们不能保证它们在你的真实工作表中能完美地工作。 那些有正则表达式经验的人都会同意,编写正则表达式是一条永无止境的完美之路--几乎总是有办法使它更优雅或能够处理更广泛的输入数据。

    从字符串中提取数字的Regex

    遵循 "从简单到复杂 "的基本教学原则,我们将从一个非常简单的案例开始:从字符串中提取数字。

    你要决定的第一件事是检索哪个号码:第一个、最后一个、特定发生的还是所有号码。

    提取第一个数字

    这是最简单的正则表达式。 鉴于\d表示从0到9的任何数字,+表示一次或多次,我们的正则表达式采取这种形式。

    样式 : \d+

    设置 实例_num 到1,你就会得到想要的结果。

    =RegExpExtract(A5, "\d+", 1)

    其中A5是原始字符串。

    为方便起见,你可以在一个预定义的单元格($A$2 )中输入模式,并用$符号锁定其地址。

    =RegExpExtract(A5, $A$2, 1)

    获取最后一个号码

    要提取一个字符串中的最后一个数字,这里要使用的模式是。

    样式 : (d+)(?!.*/d)

    翻译成人类的语言,它说:找到一个没有任何其他数字跟随(任何地方,不仅仅是立即)的数字。 为了表达这一点,我们使用一个负数的前瞻(?!.*\d),这意味着在图案的右边应该没有其他数字(\d),不管前面有多少其他字符。

    =RegExpExtract(A5, "(\d+)(?!.*\d)" )

    提示。

    • 为了获得 具体发生情况 ,使用 \d+ 表示 模式 和一个适当的序列号,用于 实例_num .
    • 提取的公式是 所有数字 在下一个例子中讨论。

    提取所有匹配的Regex

    把我们的例子再推进一步,假设你想从一个字符串中获得所有的数字,而不是只有一个。

    正如你可能记得的那样,提取的匹配数量是由可选的 实例_num 默认是全部匹配,所以你只需省略这个参数。

    =RegExpExtract(A2, "\d+")

    该公式对单个单元格来说效果很好,但在动态阵列Excel和非动态版本中的行为不同。

    Excel 365和Excel 2021

    由于对动态数组的支持,一个常规公式会自动溢出到显示所有计算结果所需的多个单元格中。 就Excel而言,这被称为溢出区域。

    Excel 2019及以下版本

    在前动态Excel中,上述公式只返回一个匹配项。 要获得多个匹配项,你需要把它变成一个数组公式。 为此,选择一个单元格区域,输入公式,然后按Ctrl + Shift + Enter完成。

    这种方法的缺点是在 "额外的单元格 "中出现了一堆#N/A错误。 遗憾的是,对此无能为力(IFERROR和IFNA都不能修复它,唉)。

    在一个单元格中提取所有匹配的内容

    当处理一列数据时,上述方法显然是行不通的。 在这种情况下,理想的解决方案是在一个单元格中返回所有的匹配结果。 要做到这一点,将RegExpExtract的结果提供给TEXTJOIN函数,并用任何你喜欢的分隔符来分隔它们,例如逗号和空格。

    =TEXTJOIN(", ", TRUE, RegExpExtract(A5, "\d+"))

    注意:由于TEXTJOIN函数仅在Excel for Microsoft 365、Excel 2021和Excel 2019中可用,该公式在旧版本中无法使用。

    从字符串中提取文本的Regex

    在Excel中,从字母数字字符串中提取文本是一项相当具有挑战性的任务。 有了regex,它变得易如反掌。 只需使用一个否定的类来匹配所有不是数字的东西。

    样式 : [^\d]+

    要获得单个单元格(溢出范围)中的子串,公式为:。

    =RegExpExtract(A5, "[^\d]+")

    要把所有的匹配结果输出到一个单元格中,可以像这样把RegExpExtract函数嵌套在TEXTJOIN中。

    =TEXTJOIN("", TRUE, RegExpExtract(A5, "[^\d]+"))

    从字符串中提取电子邮件地址的Regex

    要从一个包含大量不同信息的字符串中提取出一个电子邮件地址,请编写一个复制电子邮件地址结构的正则表达式。

    样式 : [\w\.\-]+@[A-Za-z0-9\.\-]+\.[A-Za-z]{2,24}

    分解这个词组,我们得到的结果如下。

    • [\w\.\-]+是一个用户名,可以包括1个或多个字母数字字符、下划线、点和连字符。
    • @ 符号
    • [A-Za-z0-9\.\-]+是一个域名,包括:大写和小写字母、数字、连字符和点(在子域的情况下)。 这里不允许使用下划线,因此使用3个不同的字符集(如A-Z a-z和0-9)而不是匹配任何字母、数字或下划线的\w。
    • \[A-Za-z]{2,24}是一个顶级域名,由一个点和大、小写字母组成。 大多数顶级域名的长度为3个字母(如.com.org,.edu等),但理论上它可以包含2到24个字母(最长的注册顶级域名)。

    假设字符串在A5中,模式在A2中,提取电子邮件地址的公式是。

    =RegExpExtract(A5, $A$2)

    从电子邮件中提取域名的Regex

    当谈到提取电子邮件域名时,人们首先想到的是使用一个捕捉组来寻找紧随@字符的文本。

    样式 : @([A-Za-z0-9\.\-]+\.[A-Za-z]{2,24})

    将其送入我们的正则函数。

    =RegExpExtract(A5, "@([A-Za-z0-9\.\-]+\.[A-Za-z]{2,24})")

    然后你会得到这个结果。

    在经典的正则表达式中,捕获组以外的任何东西都不包括在提取范围内。 没有人知道为什么VBA RegEx的工作方式不同,也会捕获"@"。 为了摆脱它,你可以从结果中删除第一个字符,用一个空字符串替换它。

    =REPLACE(RegExpExtract(A5, "@([a-z\d][a-z\d\-\.]*.[a-z]{2,})", 1, FALSE), 1, 1, "")

    用正则表达式提取电话号码

    电话号码有许多不同的写法,这就是为什么几乎不可能想出一个在所有情况下都有效的解决方案。 尽管如此,你可以写下你的数据集中使用的所有格式,并尝试与之匹配。

    在这个例子中,我们将创建一个将提取任何这些格式的电话号码的词条。

    (123) 345-6789

    (123) 345 6789

    (123)3456789

    123-345-6789

    123.345.6789

    123 345 6789

    1233456789

    样式 : \(?\d{3}[-\.\)]*\d{3}[-.]?\d{4}\b

    • 第一部分 \(?\d{3} 匹配零或一个开口括号,后面是三个数字d{3}。
    • [-\. \)]*部分是指方括号内出现0次或更多次的任何字符:连字符、句号、空格或闭合括号。
    • 接下来,我们又有三个数字d{3},后面是任何连字符、句号或空格[-/...]? 出现0次或1次。
    • 在这之后,有一组四位数 (d{4}。
    • 最后,有一个词的边界(b)定义,我们正在寻找的电话号码不能是一个更大的数字的一部分。

    完整的公式是这样形成的。

    =RegExpExtract(A5, "\(?\d{3}[-\. \)]*\d{3}[-\. ] ?\d{4}\b")

    请注意,上述的正则表达式可能会返回一些错误的结果,如123)456 7899或(123 456 7899。 下面的版本修复了这些问题。 然而,这种语法只在VBA正则函数中起作用,在经典正则表达式中不起作用。

    样式 : (\(\d{3}\)

    从字符串中提取日期的Regex

    一个用于提取日期的正则表达式取决于日期在字符串中出现的格式。 例如。

    要提取1/1/21或01/01/2021这样的日期,词组是:\d{1,2}\/\d{1,2}/(\d{4})

    它搜索的是一组1或2个数字d{1,2},后面是斜线,后面是另一组1或2个数字,后面是斜线,后面是一组4或2个数字(\d{4})。第一个条件在交替OR结构中被匹配,其余条件不被检查。

    要检索1-1-21或01-1-2021这样的日期,模式是:\d{1,2}-[A-Za-z]{3}-\d{2,4}。

    它搜索一组1或2个数字,后面是连字符,后面是3个大写或小写字母,后面是连字符,后面是一组4或2个数字。

    将这两种模式结合在一起后,我们得到了以下的词条。

    样式 : \b\d{1,2}[\/-](\d{1,2})

    在哪里?

    • 第一部分是1或2位数:\d{1,2}。
    • 第二部分是1或2位数字或3个字母:(\d{1,2})。
    • 第三部分是一组4位或2位的数字:(\d{4})。
    • 分隔符是正斜线或连字符:[\/-]
    • 一个词的边界(b)被放在两边,以明确日期是一个独立的词,而不是一个更大的字符串的一部分。

    正如你在下面的图片中所看到的,它成功地拉出了日期,并留下了诸如11/22/333这样的子串。 然而,它仍然返回错误的肯定结果。 在我们的案例中,A9中的子串11-ABC-2222在技术上是符合日期格式的 dd-mmm-yyy 并因此被提取出来。

    为了消除误报,你可以将[A-Za-z]{3}部分替换为3个字母的月份缩写的完整列表。

    样式 : \b\d{1,2}[\/-](\d{1,2})

    为了忽略字母大小写,我们将自定义函数的最后一个参数设置为FALSE。

    =RegExpExtract(A5, $A$2, 1, FALSE)

    而这一次,我们得到了一个完美的结果。

    从字符串中提取时间的Regex

    为了获得时间,在 hh:mm hh:mm:ss 格式,下面的表达式会很有效。

    样式 : \b(0?[0-9]

    分解这个词组,你可以看到两个部分,分别由

    表达方式1 : \b(0?[0-9]

    检索带有AM/PM的时间。

    一小时 可以是0到12之间的任何数字。 为了得到它,我们使用OR结构([0-9] )。

    • [0-9] 匹配从0到9的任何数字
    • 1[0-2] 匹配10至12的任何数字

    分钟 [0-5]d是00到59之间的任何数字。

    第二次 (:[0-5]\d)? 也是00到59之间的任何数字。 ? 量词表示零或一个出现,因为秒可能包括在时间值中,也可能不包括。

    表达方式2 : \b([0-9]

    提取不含AM/PM的时间。

    ǞǞǞ 小时 部分可以是0到32之间的任何数字。 为了得到它,需要一个不同的OR结构([0-9] )。

    • [0-9] 匹配从0到9的任何数字
    • [0-1]/d 匹配从00到19的任何数字
    • 2[0-3] 匹配20到23之间的任何数字

    ǞǞǞ 第二 部分与上述表达式1相同。

    负数的lookahead(?!:)被添加到跳过字符串中,如20:30:80。

    由于PM/AM可以是大写或小写,我们使这个函数不区分大小写。

    =RegExpExtract(A5, $A$2, 1, FALSE)

    希望上面的例子能给你一些如何在你的Excel工作表中使用正则表达式的想法。 不幸的是,并不是所有经典正则表达式的功能都能在VBA中得到支持。 如果你的任务不能用VBA RegExp完成,我鼓励你阅读下一部分,它讨论了很多更强大的.NET Regex函数。

    自定义基于.NET的Regex函数来提取Excel中的文本

    与任何Excel用户都可以编写的VBA正则函数不同,.NET RegEx是开发者的领域。 微软.NET框架支持与Perl 5兼容的全功能正则表达式语法。 本文不会教你如何编写这种函数(我不是程序员,对如何编写没有丝毫概念 :)

    由标准的.NET RegEx引擎处理的四个强大的函数已经由我们的开发人员编写并包含在Ultimate Suite中。 下面,我们将演示一些专门为提取Excel中的文本而设计的函数的实际用途。

    提示:关于.NET Regex语法的信息,请参考.NET正则表达式语言。

    如何在Excel中使用正则表达式提取毒刺

    假设你安装了最新版本的Ultimate Suite,使用正则表达式提取文本可以归结为以下两个步骤。

    1. 关于 阿博比特数据 选项卡,在 文本 组,点击 Regex工具 .
    2. 关于 Regex工具 窗格,选择源数据,输入你的Regex模式,并选择 萃取物 要想得到一个自定义函数的结果,而不是一个值,选择 作为一个公式插入 完成后,点击 萃取物 按钮。

    结果将出现在你的原始数据右边的一个新栏目中。

    AblebitsRegexExtract的语法

    我们的自定义函数有以下语法。

    AblebitsRegexExtract( reference, regular_expression)

    在哪里?

    • 参考资料 (required) - 对包含源字符串的单元格的引用。
    • 正则表达式 (required) - 匹配的反义词模式。

    重要提示!该功能只在安装了Ultimate Suite for Excel的机器上运行。

    使用说明

    为了使你的学习曲线更顺畅,使你的体验更愉快,请注意以下几点。

    1. 要创建一个公式,你可以使用我们的 Regex工具 ,或Excel的 插入功能 一旦公式被插入,你可以像管理任何本地公式一样管理它(编辑、复制或移动)。
    2. 你所输入的图案在 Regex工具 也可以将正则表达式保存在单独的单元格中。 在这种情况下,只需为第2个参数使用一个单元格引用。
    3. 该函数提取了 第一个发现的匹配 .
    4. 在默认情况下,该函数是 区分大小写 对于不区分大小写的匹配,使用(?i)模式。
    5. 如果没有找到匹配,将返回#N/A错误。

    Regex提取两个字符之间的字符串

    为了获得两个字符之间的文本,你可以使用捕捉组或查找法。

    比方说,你想提取括号之间的文本。 捕捉组是最简单的方法。

    模式1 : \[(.*?)\]

    有了积极的后看和前看,结果将是完全一样的。

    模式2 : (?<==[)(.*?)(?==])

    请注意,我们的捕获组(.*?)执行的是 懒惰的搜索 一个没有问号(.*)的抓取组将做一个 贪婪的搜索 并捕捉到从第一个[ 到最后一个] 的一切。

    在A2的模式下,公式如下。

    =AblebitsRegexExtract(A5, $A$2)

    如何获得所有的比赛

    如前所述,AblebitsRegexExtract函数只能提取一个匹配项。 要获得所有的匹配项,你可以使用我们前面讨论过的VBA函数。 然而,有一个注意事项--VBA RegExp不支持捕获组,所以上述模式也会返回 "边界 "字符,在我们的例子中就是括号。

    =TEXTJOIN(" ", TRUE, RegExpExtract(A5, $A$2))

    要去掉括号,用这个公式把它们换成空字符串("")。

    =SUBSTITUTE(SUBSTITUTE(TEXTJOIN(", ", TRUE, RegExpExtract(A5, $A$2)), "]", ""), "[", ")

    为了提高可读性,我们使用了逗号作为分隔符。

    Regex提取两个字符串之间的文本

    我们为提取两个字符之间的文本而研究出来的方法,也适用于提取两个字符串之间的文本。

    例如,要获得 "test 1 "和 "test 2 "之间的所有内容,使用以下正则表达式。

    样式 : 测试1(.*?)测试2

    完整的公式是:。

    =AblebitsRegexExtract(A5, "test 1(.*?)test 2")

    从URL中提取域名的Regex

    即使使用正则表达式,从URL中提取域名也不是一件轻而易举的事情。 做到这一点的关键因素是不抓取组。 根据你的最终目标,选择下面的一个正则表达式。

    为了获得 全域名 包括子域

    样式 : (?:https?\:

    为了获得 二级 没有子域的域名

    样式 : (?:https?\:

    现在,让我们看看这些正则表达式在以"//www.mobile.ablebits.com "为例的URL上如何工作。

    • (?:https?\:
    • \/\/ - 两个正斜线(每个正斜线前都有一个反斜线,以摆脱正斜线的特殊含义,按字面意思解释)。
    • (?:[A-Za-z\d\-\.]{2,255}?--非捕获组,用于识别第三级、第四级等域,如果有( 手机 在第一个模式中,它被放置在一个更大的捕获组中,以使所有这些子域被包括在提取中。 一个子域的长度可以是2到255个字符,因此有{2,255}的量词。
    • ([A-Za-z\d-]{1,63}\.[A-Za-z]{2,24})--提取二级域的捕获组( 能手 )和顶级域名( com 二级域名的最大长度为63个字符。 目前存在的最长的顶级域名包含24个字符。

    根据A2中输入的正则表达式,下面的公式将产生不同的结果。

    =AblebitsRegexExtract(A5, $A$2)

    Regex来提取 全域名 与所有子域。

    Regex来提取一个 二级 领域 没有子域。

    这就是如何在Excel中使用正则表达式提取部分文本的方法。 感谢你的阅读,并期待着下周在我们的博客上见到你!

    可用的下载

    Excel Regex Extract示例(.xlsm文件)。

    终极套装试用版(.exe文件)。

    Michael Brown is a dedicated technology enthusiast with a passion for simplifying complex processes using software tools. With more than a decade of experience in the tech industry, he has honed his skills in Microsoft Excel and Outlook, as well as Google Sheets and Docs. Michael's blog is dedicated to sharing his knowledge and expertise with others, providing easy-to-follow tips and tutorials for improving productivity and efficiency. Whether you're a seasoned professional or a beginner, Michael's blog offers valuable insights and practical advice for getting the most out of these essential software tools.