在 Excel 中使用正则表达式 (RegExp) 解析文本

在 Excel 中使用正则表达式 (RegExp) 解析文本在 Excel 中处理文本时,最耗时和最令人沮丧的任务之一是 解析 – 将字母数字“粥”解析成组件并从中提取我们需要的片段。 例如:

  • 从地址中提取邮政编码(如果邮政编码总是在开头很好,但如果不是呢?)
  • 从银行对账单中的付款说明中查找发票编号和日期
  • 从交易对手列表中公司的杂乱无章的描述中提取 TIN
  • 在描述等中搜索车号或货号。

通常在这种情况下,在手动挑选文本半小时后,脑海中就会开始想办法以某种方式自动化这个过程(尤其是在有大量数据的情况下)。 有几种解决方案,并且具有不同程度的复杂性效率:

  • 使用 内置 Excel 文本函数 搜索剪切胶水文本: 左室SIMV (剩下), (对), PSTR (中), STEPIT (连接) 及其类似物, 结合 (联合文本), 精确 (精确的) 等如果文本中有清晰的逻辑(例如索引始终在地址的开头),则此方法很好。 否则,公式会变得更加复杂,有时甚至会涉及到数组公式,这在大型表上会大大减慢速度。
  • 运用 像文本相似度算子 来自包装在自定义宏函数中的 Visual Basic。 这允许您使用通配符(*、#、? 等)实现更灵活的搜索。不幸的是,此工具无法从文本中提取所需的子字符串 - 仅检查它是否包含在其中。

除了上述之外,还有另一种在专业程序员、Web 开发人员和其他技术人员的小圈子中非常知名的方法——这就是 正则表达式 (正则表达式 = RegExp = “regexps” = “regulars”)。 简单的说, RegExp 是一种语言,其中特殊字符和规则用于在文本中搜索必要的子字符串,提取它们或用其他文本替换它们. 正则表达式是一个非常强大和漂亮的工具,它超越了所有其他处理文本的方式一个数量级。 许多编程语言(C#、PHP、Perl、JavaScript……)和文本编辑器(Word、Notepad++……)都支持正则表达式。

不幸的是,Microsoft Excel 没有开箱即用的 RegExp 支持,但这可以通过 VBA 轻松修复。 从选项卡打开 Visual Basic 编辑器 开发人员 (开发商) 或键盘快捷键 其他+F11. 然后通过菜单插入新模块 插入 - 模块 并在那里复制以下宏函数的文本:

公共函数 RegExpExtract(Text As String, Pattern As String, Optional Item As Integer = 1) As String On Error GoTo ErrHandl Set regex = CreateObject("VBScript.RegExp") regex.Pattern = Pattern regex.Global = True If regex.Test (Text) Then Set matches = regex.Execute(Text) RegExpExtract = matches.Item(Item - 1) Exit Function End If ErrHandl: RegExpExtract = CVErr(xlErrValue) End Function  

我们现在可以关闭 Visual Basic 编辑器并返回 Excel 来试用我们的新功能。 它的语法如下:

=RegExpExtract(文本;模式;项目)

哪里

  • TXT – 一个包含我们正在检查的文本的单元格,并且我们想要从中提取我们需要的子字符串
  • 模式 – 子字符串搜索的掩码(模式)
  • Item – 要提取的子串的序号,如果有多个(如果没有指定,则显示第一个出现)

当然,这里最有趣的是 Pattern——RegExp 的“语言中”特殊字符的模板字符串,它指定了我们想要找到的确切内容和位置。 以下是帮助您入门的最基本内容:

 模式  课程描述
 . 最简单的是一个点。 它匹配指定位置的模式中的任何字符。
 s 任何看起来像空格的字符(空格、制表符或换行符)。
 S
先前模式的反变体,即任何非空白字符。
 d
任何数字
 D
前一个的反变体,即任何非数字
 w 任何拉丁字符 (AZ)、数字或下划线
 W 前一个的反变体,即不是拉丁文,不是数字,也不是下划线。
[字符] 在方括号中,您可以指定文本中指定位置允许的一个或多个字符。 例如 艺术 将匹配任何单词: or 椅子.

您也可以不枚举字符,而是将它们设置为由连字符分隔的范围,即,而不是 [ABCDEF][自动对焦]. 或者相反 [4567] 介绍 [-4 7]. 例如,要指定所有西里尔字符,您可以使用模板 [a-yaA-YayoYo].

[^字符] 如果在左方括号后添加符号“盖子” ^,则该集合将获得相反的含义——在文本中的指定位置,所有字符都将被允许,除了列出的字符。 是的,模板 [^ЖМ]ut 会发现 途径 or 物质 or 忘记, 但不是 可怕 or 勇气,例如。
 | 布尔运算符 OR (要么) 检查任何指定的标准。 例如 (с周四|s偶数|发票) 将在文本中搜索任何指定的单词。 通常,一组选项括在括号中。
 ^ 行首
 $ 行结束
 b 词尾

如果我们正在寻找一定数量的字符,例如,一个六位数的邮政编码或所有三个字母的产品代码,那么我们就会来救援 量词 or 量词 是指定要搜索的字符数的特殊表达式。 量词应用于它之前的字符:

  量子  课程描述
 ? 零次或一次出现。 例如 .? 将意味着任何一个字符或它的缺席。
 + 一个或多个条目。 例如 d+ 表示任意位数(即 0 到无穷大之间的任意数)。
 * 零次或多次出现,即任意数量。 所以 s* 表示任意数量的空格或没有空格。
{} or

{number1,number2}

如果您需要指定严格定义的出现次数,则在花括号中指定。 例如 d{6} 严格表示六位数,而模式 小号{2,5} – 两到五个空格

现在让我们进入最有趣的部分——分析创建函数的应用以及我们从生活中的实际例子中学到的模式。

从文本中提取数字

首先,我们来分析一个简单的案例——你需要从字母数字粥中提取第一个数字,例如,从价目表中提取不间断电源的功率:

在 Excel 中使用正则表达式 (RegExp) 解析文本

正则表达式背后的逻辑很简单: d 表示任何数字,量词 + 说他们的人数应该是一个或多个。 函数前面的双减号用于“即时”将提取的字符从数字文本转换为完整数字。

邮编

乍一看,这里的一切都很简单——我们要连续查找六位数。 我们使用特殊字符 d 用于数字和量词 6、XNUMX、XNUMX、XNUMX {} 对于字符数:

在 Excel 中使用正则表达式 (RegExp) 解析文本

但是,当行中的索引左侧有一大组连续的数字(电话号码、TIN、银行账户等)时,可能会出现这种情况。那么我们的常规赛将提取前 6 个来自它的数字,即无法正常工作:

在 Excel 中使用正则表达式 (RegExp) 解析文本

为了防止这种情况发生,我们需要在正则表达式的边缘添加一个修饰符 b 表示一个词的结束。 这将使 Excel 清楚我们需要的片段(索引)应该是一个单独的单词,而不是另一个片段(电话号码)的一部分:

在 Excel 中使用正则表达式 (RegExp) 解析文本

电话

在文本中查找电话号码的问题在于,书写数字有很多选择——带或不带连字符、通过空格、带或不带括号中的地区代码等。因此,在我看来,更容易首先使用几个嵌套函数从源文本中清除所有这些字符 替代 (代替)使它粘在一起成为一个整体,然后用一个原始的规则 d{11} 连续拉出11个数字:

在 Excel 中使用正则表达式 (RegExp) 解析文本

ITN

这里有点复杂,因为 TIN(在我国)可以是 10 位(对于法人实体)或 12 位(对于个人)。 如果你不特别挑毛病,那么很可能满足于常规 d{10,12},但严格来说,它会拉出所有10到12个字符的数字,即错误输入的11位数字。 使用由逻辑 OR 运算符连接的两个模式会更正确 | (竖线):

在 Excel 中使用正则表达式 (RegExp) 解析文本

请注意,在查询中,我们首先查找 12 位数字,然后才查找 10 位数字。 如果我们以相反的方式编写正则表达式,那么它将为所有人提取出来,即使是长的 12 位 TIN,也只有前 10 个字符。 即第一个条件触发后,不再进行进一步验证:

在 Excel 中使用正则表达式 (RegExp) 解析文本

这是运营商的根本区别 | 来自标准的 excel 逻辑函数 OR (要么),重新排列参数不会改变结果。

产品 SKU

在许多公司中,唯一标识符被分配给商品和服务——文章、SAP 代码、SKU 等。如果它们的符号中有逻辑,那么可以使用正则表达式轻松地将它们从任何文本中提取出来。 例如,如果我们知道我们的文章总是由三个大写英文字母、一个连字符和一个随后的三位数字组成,那么:

在 Excel 中使用正则表达式 (RegExp) 解析文本

模板背后的逻辑很简单。 [阿兹] – 表示拉丁字母的任何大写字母。 下一个量词 3、XNUMX、XNUMX、XNUMX {} 说对我们来说重要的是恰好有三个这样的字母。 在连字符之后,我们正在等待三位数字,所以我们在末尾添加 d{3}

现金金额

与上一段类似,您还可以从商品描述中提取价格(成本、增值税……)。 例如,如果货币金额用连字符表示,则:

在 Excel 中使用正则表达式 (RegExp) 解析文本

模式 d 带量词 + 搜索直到连字符的任何数字,并且 d{2} 之后会寻找便士(两位数)。

如果您需要提取的不是价格而是增值税,那么您可以使用我们的 RegExpExtract 函数的第三个可选参数,它指定要提取的元素的序号。 而且,当然,您可以替换该功能 替代 (代替) 在结果中,标准小数分隔符的连字符并在开头添加一个双减号,以便 Excel 将找到的增值税解释为正常数字:

在 Excel 中使用正则表达式 (RegExp) 解析文本

车牌号

如果不乘坐特种车辆、拖车等摩托车,那么标准车号按照“字母-三个数字-两个字母-地区代码”的原则进行解析。而且,区域码可以是2位或3位数字,并且只有那些与拉丁字母相似的字母才被用作字母。因此,以下正则表达式将帮助我们从文本中提取数字:

在 Excel 中使用正则表达式 (RegExp) 解析文本

时间

要以 HH:MM 格式提取时间,以下正则表达式适用:

在 Excel 中使用正则表达式 (RegExp) 解析文本

结肠片段后 [0-5]天,因为它很容易计算出来,设置在 00-59 范围内的任何数字。 在括号中的冒号之前,有两种模式起作用,由逻辑 OR(竖线)分隔:

  • [0-1]天 – 00-19 范围内的任何数字
  • 2[0-3] – 20-23 范围内的任何数字

对于获得的结果,您可以另外应用标准 Excel 函数 时间 (团队)将其转换为程序可以理解并适合进一步计算的时间格式。

密码检查

假设我们需要检查用户发明的密码列表是否正确。 根据我们的规定,密码只能包含英文字母(小写或大写)和数字。 不允许使用空格、下划线和其他标点符号。

可以使用以下简单的正则表达式来组织检查:

在 Excel 中使用正则表达式 (RegExp) 解析文本

事实上,对于这样的模式,我们要求在开始 (^) 并结束 ($) 在我们的文本中,只有方括号中给出的集合中的字符。 如果您还需要检查密码的长度(例如,至少 6 个字符),那么量词 + 可以用表格中的间隔“六或更多”代替 {6,}:

在 Excel 中使用正则表达式 (RegExp) 解析文本

来自地址的城市

假设我们需要从地址栏中提取城市。 常规程序会有所帮助,从“g”中提取文本。 到下一个逗号:

在 Excel 中使用正则表达式 (RegExp) 解析文本

让我们仔细看看这个模式。

如果您已经阅读了上面的文字,那么您已经了解了正则表达式中的某些字符(句点、星号、美元符号等)具有特殊含义。 如果您需要自己查找这些字符,则它们前面有一个反斜杠(有时称为 屏蔽)。 因此,在搜索片段“g”时。 我们必须用正则表达式写 先生。 如果我们正在寻找一个加号,那么 + 等等

我们模板中接下来的两个字符,点和量词星号,代表任意数量的任意字符,即任意城市名称。

模板末尾有一个逗号,因为我们正在寻找来自“g”的文本。 逗号。 但是文本中可以有几个逗号,对吗? 不仅是城市,还包括街道、房屋等。我们的请求将停止在哪一个? 这就是问号的用途。 没有它,我们的正则表达式将拉出可能的最长字符串:

在 Excel 中使用正则表达式 (RegExp) 解析文本

就正则表达式而言,这样的模式是“贪婪的”。 为了纠正这种情况,需要一个问号——它使量词“吝啬”——我们的查询只将文本带到“g”之后的第一个反逗号:

在 Excel 中使用正则表达式 (RegExp) 解析文本

来自完整路径的文件名

另一种非常常见的情况是从完整路径中提取文件名。 表单的简单正则表达式将在这里有所帮助:

在 Excel 中使用正则表达式 (RegExp) 解析文本

这里的技巧是搜索实际上是在相反的方向上发生的——从结尾到开头,因为在我们模板的末尾是 $, 我们正在寻找它之前的所有内容,直到右边的第一个反斜杠。 反斜杠被转义,就像前面示例中的点一样。

PS

“接近尾声” 我想澄清以上所有内容只是正则表达式提供的所有可能性的一小部分。 有很多特殊字符和它们的使用规则,整本书都是关于这个主题的(我推荐至少这本书作为开始)。 在某种程度上,编写正则表达式几乎是一门艺术。 几乎总是可以改进或补充发明的正则表达式,使其更优雅或能够处理更广泛的输入数据。

分析和解析别人的正则表达式或调试自己的,有几个方便的在线服务: 正则表达式101, 正则表达式 和更多

不幸的是,并非经典正则表达式的所有功能都在 VBA 中得到支持(例如,反向搜索或 POSIX 类)并且可以与 Cyrillic 一起使用,但我认为第一次满足您的需求就足够了。

如果您对该主题并不陌生,并且您有一些东西要分享,请在下面的评论中留下在 Excel 中工作时有用的正则表达式。 一个头脑是好的,但两个靴子是一对!

  • 使用 SUBSTITUTE 函数替换和清理文本
  • 搜索并突出显示文本中的拉丁字符
  • 搜索最接近的相似文本(Ivanov = Ivonov = Ivanof 等)

发表评论