ABAP 中使用正则表达式的一点知识分享

作者:郑德鼎 约 7 分钟阅读 更新日期:2025-03-02 1 年前更新 标签:ABAP, CO, Data Engineering, FI, SD, 开发, 数据工程, 财务, 销售分销
ABAP 中使用正则表达式的一点知识 - 封面图
ABAP 中使用正则表达式的一点知识 - 封面图

ABAP中提供了足够的处理字符串的内置方法,一般情况下,遇到字符串处理,我们都会下意识地写一块代码,Find、Replace、Split、abc+m(n)、CS/CO/CA/CN等等组合起来,基本上所有情形都能涵盖。但有时难免遇到正则表达式,比如这样一个张牙舞爪的字符串,^

(-?[0-9]{1,12})(\\.[0-9]{0,3})?$,学名正则表达式(Regular

Expression,RegEx),具体是什么意思。我们可能不用必须会写,但能读懂正则表达式也算一项小小的技能。

一般情况下,我们能够根据代码的前后文推测出这一串字符是做什么的,比如上文这个正则表达式是用来筛选数值的,SAP中的数值一般是数量或者金额,如果一个字段的值符合此

RegEx 的所有检查项,则表明它是一个数量或金额值。 正则表达式有IEEE发布的规范,基本上所有语言通用。在ABAP中,RegEx一般配合

cl_abap_matcher、find、replace使用。举个例子:

IF cl_abap_matcher=>matches(                 pattern = '^(-?[0-9]{1,12})(\.[0-9]{1,3})?$'                                         text = lv_data_value                  ) = abap_true. cl_demo_output=>write( |{ lv_data_value }是金额或数量值| ).ELSE.   cl_demo_output=>write( |{ lv_data_value }不是金额或数量值| ).ENDIF.

运行结果如下:

ABAP 中使用正则表达式的一点知识 - 封面图
ABAP 中使用正则表达式的一点知识 - 封面图

lv_data_value赋新值。

*

lv_data_value = '1K.78'.

运行结果如下:

ABAP 中使用正则表达式的一点知识 - 封面图
ABAP 中使用正则表达式的一点知识 - 封面图

具体这段正则表达式

^(-?[0-9]{1,12})(\\.[0-9]{1,3})?$的各部分代表什么含义,简单解释一下。^和$表示开始和结束,从头到尾全检查;-?表示 **

有0个或1个负号 ; ** [0-9]{1,12}表示要 ** 有1-12位数字 **

,第一个括号结束,表示第一段匹配逻辑结束;第二个括号和第一个括号中间没有运算符,则表示取交集。\\.表示1个小数点,

[0-9]{1,3}顾名思义,要有1-3位数字,也就是1-3位小数值;最后一个?表示这一段逻辑 (\\.[0-9]{1,3})可以匹配到0次或1次,也就是

**可以没有小数点及小数位,如果有小数点则必须含1-3位小数** 。加粗内容其实就是抽象出来的判断数值的逻辑,再在这个逻辑基础上抽象成正则表达式。

再比如这个正则表达式,^[a-zA-Z0-9_.-]+@[a-zA-Z0-9]{2,10}(.[a-z]{2,6}){1,3}$,这是验证email的一个RegEx,[a-zA-Z0-9_.-]+表示有若干大小写字母、数字、下划线、连接符、点组成的字符串,@表示强制必须有一个@符号,[a-zA-Z0-9]{2,10}表示@符号后面是大小写字母和数字成成的2-10位的字符串,(.[a-z]{2,6}){1,3}表示有1到3组由点和字母组成的长度在2-6位的字符串,即.com,.net这类。验证一下。

lv_data_value = 'ab_c.1-23@xyz.com'.IF cl_abap_matcher=>matches( pattern = '^[a-zA-Z0-9_.-]+@[a-zA-Z0-9]{2,10}(.[a-z]{2,6}){1,3}$'             text = lv_data_value                             ) = abap_true.  cl_demo_output=>write( |{ lv_data_value }是Email地址| ).ENDIF.

运行结果如下:

ABAP 中使用正则表达式的一点知识 - 封面图
ABAP 中使用正则表达式的一点知识 - 封面图

你可以挑战一下这个RegEx,比如加一些特殊字符,加很多个.com之类的后缀,看一下还能不能通过验证。

再讲一个很有名的例子,给金额加千分符。比如我拿出一串金额,

12345678.33500,让你加上千分符。当然所有RegEx的处理都是以转换成字符串为前提。这里其实就涉及Replace的使用。代码如下:

lv_data_value = '12345678.33500'.REPLACE ALL OCCURRENCES OF REGEX '(?=(?!^)(?:\d{3})+(?:\.))' IN lv_data_value WITH ','.

(?=(?!^)(?:\d{3})+(?:\\.))这个RegEx可能读起来比较费劲,它的整体含义是,找到符合“3个数字为一组的若干组数字字符以及紧跟着的小数点,并标记匹配的位置”。小数不加千分符,所以小数点后面不用理会。圆括号里带一个?:表示不缓存,不然系统会把匹配到的字符串写进cache,Replace的时候会把匹配到的字符串替换成千分符,而不是把匹配的位置替换成千分符,造成“,,.000”这种结果。?=表示记录位置,配合ALL

OCCURRENCES OF,每次匹配都会从上次匹配的位置,而不是从头开始。

(?!^)表示如果匹配到的位置是开头,则不匹配,这是为了避免出现“,123.000”这种情形。运行结果如下:

ABAP 中使用正则表达式的一点知识 - 封面图
ABAP 中使用正则表达式的一点知识 - 封面图

有个比较常见的场景,不知道大家有没有思考过,就是各种短信验证码。输入法会自动从短信中把验证码截取出来,让你直接粘贴,这是怎么实现的。比如有这样一条验证短信,“【网易】验证码:685733,您正在登录网易账号(若非本人操作,请删除本短信)”,怎样把685733精确提取出来?那就要分析验证码的前后文特征。短信中必然有‘验证码’三个字,验证码一定是纯数字的,6位或4位,验证码三个字和数字之间可能有冒号或者其他字符,或者什么也没有。有这3个特征,就可以写RegEx了。用ABAP实现一下。

DATA:lv_string_sms TYPE char100.DATA lv_valid_code(6).lv_string_sms = '【网易】验证码:685733,您正在登录网易账号(若非本人操作,请删除本短信)'. FIND ALL OCCURRENCES OF REGEX '验证码\D*(?:\d{6}|\d{4})' IN lv_string_sms MATCH COUNT DATA(l_match_count) RESULTS DATA(lt_reg_results).DATA(ls_reg_result) = VALUE #( lt_reg_results[ 1 ] OPTIONAL ).IF ls_reg_result IS NOT INITIAL. DATA(lv_sub_str) = CONV char20( lv_string_sms+ls_reg_result-offset(ls_reg_result-length) ). DATA(lv_len) = strlen( lv_sub_str ) - 6. IF cl_abap_matcher=>matches( pattern = '(\D*[0-9]+)' text = lv_sub_str+lv_len(6) ) = abap_true. lv_len = strlen( lv_sub_str ) - 4. lv_valid_code = lv_sub_str+lv_len(4). ELSE. lv_valid_code = lv_sub_str+lv_len(6). ENDIF. cl_demo_output=>write( lv_valid_code ).ENDIF.

ABAP代码就不多做解释了。运行结果如下:

ABAP 中使用正则表达式的一点知识 - 封面图
ABAP 中使用正则表达式的一点知识 - 封面图

换成4位也一样。'【 某某平台 】验证码:9876,您正在登录某某平台,请在3分钟内输入'

ABAP 中使用正则表达式的一点知识 - 封面图
ABAP 中使用正则表达式的一点知识 - 封面图

大家有闲暇可以思考一下如果另外一种验证短信怎么处理,类似这种,“【某某平台】654321(此为验证码,请在1分钟内输入)”。‘验证码’3个字在后面。

大部分日常用到的正则表达式都能在网上查到, 同一个验证逻辑可能有多种写法。 网上有大量的资料,大家可以多研究。

但网上的东西未必靠谱,也不一定完全契合你的需求,在使用之前最好反复验证。

郑德鼎

关于作者:郑德鼎

企业信息化与 SAP 技术顾问,长期专注 SAP ABAP、FI/CO、MM、SD 等模块的技术分享与实战经验总结。查看更多介绍

来源说明:本文内容由「ABAP中使用正则表达式的一点知识分享.md」整理生成,仅用于内部技术分享与学习交流。