SAP ABAP 字串內數字去前導零的兩種方法(正則/拼接)

狐嫁發表於2024-06-18

碰到一個小需求,需要把字串裡數字的前導0給去掉。

ABAP內,想對字串做處理,把字串內的數字進行去前導0,通常有兩種思路,拆分處理再拼接或者直接用正則表達替換。

最初的想法是直接透過符號拆分,去前導0後拼回去,但是瞭解到實際分割的符號並不唯一。

所以直接用正規表示式來做替換會更加合適。

透過0(\d)來去掉0,0(\d)代表的是0+數字,透過這個方法可以去掉一到兩位數字的前導0

點選檢視程式碼
WRITE:/,'*透過0(\d)來去掉0,0(\d)代表的是0+數字,透過這個方法可以去掉一到兩位數字的前導0'.
DATA    text2   TYPE string VALUE '01,02,04;03,05,08;06,09,010,20,025'.
WRITE:/,'去前導0之前的字串:',text2.
REPLACE ALL OCCURRENCES OF REGEX '0(\d)' IN text2 WITH '$1'.
WRITE:/,'去前導0之後的字串:',text2.

效果圖:

但是我發現,如果出現3位數字的情況,會出BUG,比如105直接替換成15了

點選檢視程式碼
WRITE:/,'*但是當出現三位數時,0(\d)是什麼效果呢?'.
DATA    text3   TYPE string VALUE '01,04,05;02,05,06;08,09,10,18;90,100,105,110'.
WRITE:/,'去前導0之前的字串:',text3.
REPLACE ALL OCCURRENCES OF REGEX '0(\d)' IN text3 WITH '$1'.
WRITE:/,'去前導0之後的字串:',text3.
WRITE:/,'*可以看到,三位數數字的0一樣會被刪掉'.

效果圖:

為了避免出現可能會出現的三位數BUG,所以匹配的字元多一位,採用(\D)0(\d),非數字+0+數字來作為匹配。

但是這樣就漏掉開頭的第一個數字了,所以再加一步[1]+去字元開頭的前導0。

點選檢視程式碼
WRITE:/,'*為了適應字串記憶體在三位數及以上的情況,增加一個匹配項變成(\D)0(\d),這代表的是非數字+0+數字'.
WRITE:/,'*但是這樣就會漏掉開頭第一個數字,因為缺少了非數字的匹配項,所以加一步^[0]+,去掉開頭的前導0'.
DATA    text4   TYPE string VALUE '01,04,05;02,05,06;08,09,010,18;090,0100,0105,0110'.
WRITE:/,'去前導0之前的字串:',text4.
REPLACE ALL OCCURRENCES OF REGEX '(\D)0(\d)' IN text4 WITH '$1$2'.
WRITE:/,'透過(\D)0(\d)去前導0的字串:',text4.
REPLACE ALL OCCURRENCES OF REGEX '^[0]+'     IN text4 WITH ''.
WRITE:/,'再去掉開頭的前導0的字串',text4.

效果圖:

那麼如果不用正則替換,怎麼用拼接的方式實現去掉字串裡的前導零呢?

假如間隔的符號是固定的,直接拆分去前導零做拼接就行了。

點選檢視程式碼
DATA text0   TYPE string VALUE '01,02,04,03,05,08,06,09,10,15,20,30,50,105,120'.
DATA txt0    TYPE string.
DATA num0(2) TYPE c VALUE 0.

WRITE:/,'*對固定符號間隔的字串做處理,直接拆分做去前導0即可'.
WRITE:/,'去前導0之前的字串:',text0.
*分割符號固定
*透過,分割放入內表
SPLIT text0 AT ',' INTO TABLE DATA(lt_text).

*去前導0後重新拼接
LOOP AT lt_text ASSIGNING FIELD-SYMBOL(<lt_text>).

  <lt_text> = |{ <lt_text> ALPHA = OUT }|.
  txt0 = |{ txt0 }{ COND #( WHEN txt0 IS NOT INITIAL THEN ',' ELSE '') }{ CONV dec03( <lt_text> ) }|.

ENDLOOP.
WRITE:/,'去前導0之後的字串:' ,txt0.
效果圖:


但是,分隔的符號出現多個時,SPLIT直接拆分就不太好用了。

首先用正則去掉數字,用拿到的分割符號給函式segment做拆分,再做拼接。

點選檢視程式碼
DATA lt_asv   TYPE TABLE OF string .
DATA text1   TYPE string VALUE '01,02,04;03,05,08;06,09,10;15,20,30;50,105,120'.
DATA num1(3) TYPE c VALUE 0.
DATA num2(3) TYPE c VALUE 0.
DATA symbol  TYPE string.
DATA(text1_copy) = text1.

WRITE:/,'*對非固定符號間隔的字串做拆分就需要用到segment函式'.
*但是分割符號不固定怎麼辦呢
REPLACE ALL OCCURRENCES OF REGEX '[0-9]' IN text1_copy WITH ''.
WRITE:/,'去前導0之前的字串:',text1.
WRITE:/,'得到所有用於分割的符號:' ,text1_copy.
WRITE:/,'*這串字元將作為segment函式的space入參'.

DO.
  TRY.
      DATA(lv_data) = segment( val   = text1
                                index = sy-index
                                space = text1_copy ).
    CATCH cx_sy_strg_par_val.
      EXIT.
  ENDTRY.
  IF sy-subrc = 0.
    DATA:lt_data LIKE TABLE OF lv_data.
    APPEND lv_data TO lt_data.
  ENDIF.
ENDDO.

clear text1.
LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<lt_data>).
  <lt_data> = |{ <lt_data> ALPHA = OUT }|.
  num1 =  sy-tabix - 2.
  text1 = |{ text1 }{ COND #( WHEN text1 IS NOT INITIAL THEN text1_copy+num1(1) ELSE '') }{ CONV dec03( <lt_data> ) }|.
ENDLOOP.

WRITE:/,'去前導0之後的字串:',text1.

效果圖:


  1. 0 ↩︎

相關文章