文章目录前言01、案例介绍/笔者需求02、只判断是否匹配a.基础写法b.高级类写法03、获取 单个 或 多个 匹配内容a.获取 单个 匹配内容 基础写法b.获取 多个 匹配内容 基础写法c.SPLIT 的替代c.获取 单个 匹配内容 高级类写法c.获取 多个 匹配内容 高级类写法04、获取匹配位置a.基础写法b.高级类写法05、替换 删除 匹配内容a.基础写法b.高级类写法06、关系对照表a.基础常用b.常用正则表达式END、总结前言本文目前 字这篇文章会持续更新优化先点赞 关注 收藏制作不易 谢谢这篇文章给大家介绍一下ABAP中正则的用法正则是一种通用的表达式在各个语言都可以用表达式规则是不变的 只是各个语言有自己的写法我们这篇文章主要介绍ABAP中如何使用正则表达式而关于正则表达式的规则不会过多介绍。01、案例介绍/笔者需求我们会介绍ABAP正则语法的基础写法 也会介绍到正则类的用法主要就是是否匹配 、提取内容、替换内容 、获取匹配位置 等等。一般来说我们用基础写法就够用了 基础写法也比较简单快捷。SAP设计正则类 核心不是为了替代 FIND REGEX而是为了获得一些 FIND REGEX 做不到或者很麻烦做到的能力。例如为了处理 一次匹配不够、需要反复匹配、需要获取所有匹配结果、需要获取匹配对象详细信息、需要提高性能。在性能上 如果需要loop 100w次那么使用基础写法 会编译100w次 执行100w次而类的写法是编译一次 执行100w次。如果你使用正则只是想用来判断是否匹配或者其他某一个功能 并且忽略性能 那么类的写法是没有任何优势的纯粹啰嗦但是类的优势就是 正则对象可以复用比如我创建完正则对象之后 可以基于这个正则对象 判断是否匹配 也可以获取位置 捕获组等信息。02、只判断是否匹配步骤一介绍a.基础写法假设我们物料编号都是 MAT开头 并且后面是一串数字的我们要检测物料编号是否 符合编码规则可以这样写。1.用法示例‘^MAT\d$’是我们的正则表达式lv_text就是我们要检测的字符串。DATA(lv_text)MAT001.FINDREGEX^MAT\d$INlv_text.IFsy-subrc0.WRITE匹配成功.ELSE.WRITE匹配失败.ENDIF.2.正则表达式详解其中\d也可以写成[0-9]部分含义^字符串开头MAT必须是字面量 MAT\d一个数字0~9前面的内容出现 1 次或多次$以前面的内容结尾3.更多数据示例根据上面的内容 我们解析出 这个表达式的匹配的内容是MAT开头 至少一个数字 数字结尾所以得出以下结果。MAT1√MAT001√MAT99999√MAT× 没有数字MATS01× S不是数字ABC001× 不是MAT开头MAT001A× 结尾不是数字b.高级类写法1.代码示例passDATA(lv_text)MAT001.创建正则对象DATA(lo_regex)NEWcl_abap_regex(pattern^MAT\d$).创建匹配器DATA(lo_matcher)lo_regex-create_matcher(textlv_text).IFlo_matcher-match()abap_true.WRITE匹配成功.ELSE.WRITE匹配失败.ENDIF.2.步骤一 b 2pass3.步骤一 b 3pass03、获取 单个 或 多个 匹配内容步骤二介绍a.获取 单个 匹配内容 基础写法假设我们有一个字符串有物料号和物料描述组成物料号是 字母数字 物料描述就是纯中文。然后我们需要把物料号提取出来也就是提取中文之前的字符串我们可以按照如下方式提取。1.代码示例这里和判断是否匹配 多了一个关键字SUBMATCHES下面代码的意思是按照正则表达式提取字符串lv_text中的内容。使用关键字SUBMATCHES 表达式里面一定要有捕获组也就括号 。DATA(lv_text)X020150053007001成品物料.FINDREGEX^([A-Z0-9])INlv_textSUBMATCHESDATA(lv_code).WRITElv_code.2.正则表达式详解我这边列举的都比较简单其实有时候物料编码中可能还包含 - 或者其他符号如果有我们继续补充捕获组就行了。部分含义^以一个大写字母或数字字符串开头(捕获组开始[A-Z0-9]一个大写字母或数字前面的内容出现 1 次或多次)捕获组结束3.更多数据示例根据上面的内容 我们解析出 这个表达式的匹配的内容是大写字母或者数字开头 至少一个大写字母或数字 (然后遇到非大写字母或者数字结束)所以得出以下结果。MAT001√ABC123√ 123ABC √A√1√-ABC× 开头不是字母或数字 _ABC × 开头不是字母或数字ABC-123√ 匹配到ABC后面的-123不参与匹配ABC123组件 √ 匹配到ABC123后面的 “组件” 不参与匹配MAT001A√ 全部符合b.获取 多个 匹配内容 基础写法有时候一个字符串中包含多个有意义的数据例如MAT001-100 其中MAT001 是物料号100 是数量这时我们可以使用多个捕获组并通过 SUBMATCHES 一次性获取多个匹配结果。从正则语法来说捕获组 ( ) 理论上可以写很多个。不过实际开发里很少有人写超过 4~5 个捕获组。1.代码示例这里和前面的例子类似只不过定义了两个捕获组因此 SUBMATCHES 后面也需要接收两个变量。DATA(lv_text)MAT001-100.FINDREGEX^([A-Z0-9])-(\d)$INlv_textSUBMATCHESDATA(lv_matnr)DATA(lv_qty).WRITE/lv_matnr.WRITE/lv_qty.2.正则表达式详解pass部分含义^以大写字母或者数字开头(第一个捕获组开始[A-Z0-9]一个大写字母或数字前面的内容出现 1 次或多次)第一个捕获组结束-中间必须有一个减号(第二个捕获组开始\d一个数字前面的内容出现 1 次或多次)第二个捕获组结束$以数字结尾3.更多数据示例根据上面的内容我们解析出这个表达式匹配的内容是物料号(字母数字组合) - 数量(纯数字)MAT001-100√ABC123-50√X020150053007001-1√A-999√1-100√-MAT001× 减号前没有物料号MAT001-× 减号后没有数量MAT001-ABC× 数量不是数字MAT001_100× 中间不是减号MAT001-100A × 结尾不是数字ABC-123-456× 存在多余内容4.五个捕获组示例DATA(lv_text)SH-MAT001-100-2026-批次A.FINDREGEX^([A-Z])-([A-Z0-9])-(\d)-(\d)-(.)$INlv_textSUBMATCHESDATA(lv_factory)DATA(lv_matnr)DATA(lv_qty)DATA(lv_year)DATA(lv_batch).WRITE:/工厂:,lv_factory.WRITE:/物料号:,lv_matnr.WRITE:/数量:,lv_qty.WRITE:/年份:,lv_year.WRITE:/批次:,lv_batch.捕获组含义([A-Z])第1个捕获组 → 工厂全大写字母([A-Z0-9])第2个捕获组 → 物料号字母数字(\d)第3个捕获组 → 数量数字(\d)第4个捕获组 → 年份数字(.)第5个捕获组 → 批次任意字符c.SPLIT 的替代只做了解 不推荐一般分割字符串用 SPLIT 就可以了。而且 SPLIT 还可以灵活的获取多个存入内表中。1.代码示例passDATA(lv_text)MAT001,100,USD.FINDREGEX^([^,]),([^,]),([^,])$INlv_textSUBMATCHESDATA(lv_matnr)DATA(lv_qty)DATA(lv_curr).WRITE/lv_matnr.WRITE/lv_qty.WRITE/lv_curr.执行结果MAT001100USD2.正则表达式详解[^,]是正则中一个很常见的写法意思 匹配任意非逗号字符 当^写在中括号内部的时候不再是以什么什么开头 而是非什么什么。例如所以[^,]就表示连续一个或多个非逗号字符 实际上就是一直取字符直到遇到逗号停止A√1√ 中 √ $ √,×部分含义^从字符串开头开始匹配(捕获组开始[^,]除了逗号以外的任意字符前面的内容出现 1 次或多次)捕获组结束,字面量逗号$以第三个捕获组结尾3.更多数据示例根据上面的内容我们解析出这个表达式匹配的内容是第一段非逗号字符逗号第二段非逗号字符逗号第三段非逗号字符所以得出以下结果。MAT001,100,USD√ABC123,50,CNY√X020150053007001,1,EUR√A,999,JPY√1,100,USD√,100,USD× 第一个字段为空MAT001,,USD× 第二个字段为空MAT001,100,× 第三个字段为空MAT001,100× 缺少第三个字段MAT001,100,USD,TEST× 存在多余字段MAT001|100|USD× 分隔符不是逗号MAT001,100A × 缺少第三个字段c.获取 单个 匹配内容 高级类写法这个步骤的介绍1.步骤一 b 1pass2.步骤一 b 2pass3.步骤一 b 3passc.获取 多个 匹配内容 高级类写法这个步骤的介绍1.步骤一 b 1pass2.步骤一 b 2pass3.步骤一 b 3pass04、获取匹配位置有时不关心内容。只关心匹配从哪里开始a.基础写法获取匹配位置 需要使用关键字MATCH OFFSET和MATCH LENGTH1.代码示例下面代码的意思是按照正则表达式查找字符串 lv_text 中的数字并返回数字开始的位置和数字长度。DATA(lv_text)ABC12356DXYZ.FINDREGEX\dINlv_textMATCHOFFSETDATA(lv_offset)MATCHLENGTHDATA(lv_length).WRITE/lv_offset.WRITE/lv_length.最终结果 lv_offset3lv_length52.正则表达式详解这个表达式很简单就是匹配连续出现的数字 我们只是为了演示OFFSET LENGTH 的效果。部分含义\d一个数字0~9前面的内容出现 1 次或多次3.更多数据示例根据上面的内容我们解析出这个表达式匹配的内容是连续出现的数字 所以得出以下结果。字符串匹配内容OffsetLengthABC12356DXYZ1235635MAT001组件00133A123B45612313123ABC12303ABC99999933b.高级类写法这个步骤的介绍1.步骤二 a 1pass2.步骤二 a 2pass3.步骤二 a 3pass05、替换 删除 匹配内容删除其实也是替换 只是把替换的字符换为空字符串即可。 并且替换 也可以利用反向匹配 来达到提取符合要求的内容。a.基础写法假设我们有一个字符串由字母和数字组成现在需要删除所有数字只保留字母可以按照如下方式处理。1.代码示例 删除字母这里使用了 REPLACE ALL OCCURRENCES OF REGEX意思是按照正则表达式查找所有匹配内容并替换为空字符串。DATA(lv_text1)MAT123ABC456.REPLACEALLOCCURRENCESOFREGEX\dINlv_text1WITH.WRITE/lv_text1.执行结果MATABC2.正则表达式详解其中 \d 也可以写成 [0-9]。整个表达式含义匹配所有数字 由于REPLACE ALL OCCURRENCES 表示替换所有匹配项因此会把所有数字替换为空字符串。部分含义\d一个数字0~93.更多数据示例其实也可以用捕获组实现感觉REPLACE 核心更多的是替换成其他字符。MAT123ABC456→MATABC123ABC →ABCABC123→ABC123→ 空字符串ABC→ABCA1B2C3→ABC1.代码示例 提取所有数字这里利用了一个反向匹配的思路DATA(lv_text2)MAT123ABC456.REPLACEALLOCCURRENCESOFREGEX[^0-9]INlv_text2WITH.WRITE/lv_text2.1234562.正则表达式详解注意这里的 ^ 不是字符串开头因为它位于[ ]在字符集内部[^…] 表示 不属于 …部分含义[字符集开始^在字符集内表示“非”0-9数字 0~9]字符集结束3.正则表达式详解根据上面的内容我们解析出这个表达式匹配的内容是所有非数字字符。由于匹配到的内容会被替换为空字符串因此最终只剩数字。所以得出以下结果。MAT123ABC456→123456123ABC →123ABC123→123123→123ABC→ 空字符串A1B2C3→123b.高级类写法这个步骤的介绍1.步骤二 a 1pass2.步骤二 a 2pass3.步骤二 a 3pass06、关系对照表a.基础常用1.示例正则含义\d数字[0-9]数字\D非数字[^0-9]非数字[A-Z]大写字母[a-z]小写字母[A-Za-z]所有字母[A-Z0-9]大写字母或数字b.常用正则表达式1.示例END、总结以上就是今天要讲的内容本文仅仅简单介绍了ABAP中的正则表达式用法感觉这篇文章自己有学到东西或者在今后的工作中能派上用场可以点赞收藏支持制作不易非常感谢当然如果有说错或者不好的地方还望大家提出来见谅欢迎大家评论指出不好的地方。谢谢