SAP ABAP 字符串内数字去前导零的两种方法(正则/拼接)

嚴華  金牌会员 | 2024-6-18 14:20:47 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 916|帖子 916|积分 2748

遇到一个小需求,需要把字符串里数字的前导0给去掉。

ABAP内,想对字符串做处理,把字符串内的数字进行去前导0,通常有两种思路,拆分处理再拼接大概直接用正则表达替换。
最初的想法是直接通过符号拆分,去前导0后拼归去,但是了解到实际分割的符号并不唯一。
所以直接用正则表达式来做替换会更加合适。
通过0(\d)来去掉0,0(\d)代表的是0+数字,通过这个方法可以去掉一到两位数字的前导0
点击查看代码
  1. WRITE:/,'*通过0(\d)来去掉0,0(\d)代表的是0+数字,通过这个方法可以去掉一到两位数字的前导0'.
  2. DATA    text2   TYPE string VALUE '01,02,04;03,05,08;06,09,010,20,025'.
  3. WRITE:/,'去前导0之前的字符串:',text2.
  4. REPLACE ALL OCCURRENCES OF REGEX '0(\d)' IN text2 WITH '$1'.
  5. WRITE:/,'去前导0之后的字符串:',text2.
复制代码
效果图:

但是我发现,如果出现3位数字的情况,会出BUG,比如105直接替换成15了
点击查看代码
  1. WRITE:/,'*但是当出现三位数时,0(\d)是什么效果呢?'.
  2. DATA    text3   TYPE string VALUE '01,04,05;02,05,06;08,09,10,18;90,100,105,110'.
  3. WRITE:/,'去前导0之前的字符串:',text3.
  4. REPLACE ALL OCCURRENCES OF REGEX '0(\d)' IN text3 WITH '$1'.
  5. WRITE:/,'去前导0之后的字符串:',text3.
  6. WRITE:/,'*可以看到,三位数数字的0一样会被删掉'.
复制代码
效果图:

为了避免出现可能会出现的三位数BUG,所以匹配的字符多一位,采用(\D)0(\d),非数字+0+数字来作为匹配。
但是这样就遗漏开头的第一个数字了,所以再加一步[1]+去字符开头的前导0。
点击查看代码
  1. WRITE:/,'*为了适应字符串内存在三位数及以上的情况,增加一个匹配项变成(\D)0(\d),这代表的是非数字+0+数字'.
  2. WRITE:/,'*但是这样就会漏掉开头第一个数字,因为缺少了非数字的匹配项,所以加一步^[0]+,去掉开头的前导0'.
  3. DATA    text4   TYPE string VALUE '01,04,05;02,05,06;08,09,010,18;090,0100,0105,0110'.
  4. WRITE:/,'去前导0之前的字符串:',text4.
  5. REPLACE ALL OCCURRENCES OF REGEX '(\D)0(\d)' IN text4 WITH '$1$2'.
  6. WRITE:/,'通过(\D)0(\d)去前导0的字符串:',text4.
  7. REPLACE ALL OCCURRENCES OF REGEX '^[0]+'     IN text4 WITH ''.
  8. WRITE:/,'再去掉开头的前导0的字符串',text4.
复制代码
效果图:

那么如果不用正则替换,怎么用拼接的方式实现去掉字符串里的前导零呢?
假如间隔的符号是固定的,直接拆分去前导零做拼接就行了。
点击查看代码
  1. DATA text0   TYPE string VALUE '01,02,04,03,05,08,06,09,10,15,20,30,50,105,120'.
  2. DATA txt0    TYPE string.
  3. DATA num0(2) TYPE c VALUE 0.
  4. WRITE:/,'*对固定符号间隔的字符串做处理,直接拆分做去前导0即可'.
  5. WRITE:/,'去前导0之前的字符串:',text0.
  6. *分割符号固定
  7. *通过,分割放入内表
  8. SPLIT text0 AT ',' INTO TABLE DATA(lt_text).
  9. *去前导0后重新拼接
  10. LOOP AT lt_text ASSIGNING FIELD-SYMBOL(<lt_text>).
  11.   <lt_text> = |{ <lt_text> ALPHA = OUT }|.
  12.   txt0 = |{ txt0 }{ COND #( WHEN txt0 IS NOT INITIAL THEN ',' ELSE '') }{ CONV dec03( <lt_text> ) }|.
  13. ENDLOOP.
  14. WRITE:/,'去前导0之后的字符串:' ,txt0.
复制代码
效果图:

但是,分隔的符号出现多个时,SPLIT直接拆分就不太好用了。
首先用正则去掉数字,用拿到的分割符号给函数segment做拆分,再做拼接。
点击查看代码
  1. DATA lt_asv   TYPE TABLE OF string .
  2. DATA text1   TYPE string VALUE '01,02,04;03,05,08;06,09,10;15,20,30;50,105,120'.
  3. DATA num1(3) TYPE c VALUE 0.
  4. DATA num2(3) TYPE c VALUE 0.
  5. DATA symbol  TYPE string.
  6. DATA(text1_copy) = text1.
  7. WRITE:/,'*对非固定符号间隔的字符串做拆分就需要用到segment函数'.
  8. *但是分割符号不固定怎么办呢
  9. REPLACE ALL OCCURRENCES OF REGEX '[0-9]' IN text1_copy WITH ''.
  10. WRITE:/,'去前导0之前的字符串:',text1.
  11. WRITE:/,'得到所有用于分割的符号:' ,text1_copy.
  12. WRITE:/,'*这串字符将作为segment函数的space入参'.
  13. DO.
  14.   TRY.
  15.       DATA(lv_data) = segment( val   = text1
  16.                                 index = sy-index
  17.                                 space = text1_copy ).
  18.     CATCH cx_sy_strg_par_val.
  19.       EXIT.
  20.   ENDTRY.
  21.   IF sy-subrc = 0.
  22.     DATA:lt_data LIKE TABLE OF lv_data.
  23.     APPEND lv_data TO lt_data.
  24.   ENDIF.
  25. ENDDO.
  26. clear text1.
  27. LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<lt_data>).
  28.   <lt_data> = |{ <lt_data> ALPHA = OUT }|.
  29.   num1 =  sy-tabix - 2.
  30.   text1 = |{ text1 }{ COND #( WHEN text1 IS NOT INITIAL THEN text1_copy+num1(1) ELSE '') }{ CONV dec03( <lt_data> ) }|.
  31. ENDLOOP.
  32. WRITE:/,'去前导0之后的字符串:',text1.
复制代码
效果图:



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

嚴華

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表