[語法探索]如何取abap字符串的最后N位


眾所周知,ABAP提供了字符串截取語法,但是只支持從某位起取N位,不支持取后幾位。

但是實際又會有所需求,正好和群友討論起,就順便分享一下,順便研究下每種方式的優劣。

 

方法一

 DATA lv_str TYPE string VALUE 'abcdefghigk'.
 DATA(lv_len) = strlen( lv_str ) - 5.
 DATA(lv_str_out1) = lv_str+lv_len(5).  

這無疑是最常規的方式,也很容易看懂,代碼也很簡潔,不過要注意,offset本身的語法是會有異常的,尤其是用變量之后,我們首先要確保長度是大於等於5的,這樣才是有效的offset,不然會dump掉。

方法二(來自群友句號大佬):

CALL FUNCTION 'STRING_REVERSE'
  exporting
     string = lv_char
     lang     = sy-langu
   importing
     rstring = lv_char.

DATA(lv_str_out2) = lv_char+(5).

CALL FUNCTION 'STRING_REVERSE'
  exporting
     string = lv_str_out2
     lang   = sy-langu
   importing
     rstring = lv_str_out2.  

這語法看起來...也很容易懂,就是反轉再取值再反轉。

注意點有兩個,第一個同上,lv_char長度小於5會炸,第二...這坑FM雖然叫'STRING_REVERSE', 但是不支持string類型,只支持char,所以如果是長度不定的字符串,如下代碼可以代替該FM(也是抄來的):

 DATA:lv_str  TYPE string VALUE 'abc',
      lv_i    TYPE int4,
      lv_j    TYPE int4,
      rstring TYPE string.

 lv_i = strlen( lv_str ).

 DO lv_i TIMES.
   CONCATENATE lv_str+lv_j(1) rstring INTO rstring.
   lv_j = lv_j + 1.
 ENDDO.  

該LOOP實現了字符串的反轉,所以結論是,我們只需要三步,先loop反轉,再取值,再loop反轉,即可得到結果,這樣一來,我們只用了十幾行代碼,就實現了最上面2行代碼能實現的功能。

經過群里另一位大佬(寶寶)的提醒,該語法可以簡單寫為:

DATA(lv_str_out5) = reverse( lv_str ).
lv_str_out5 = reverse( lv_str_out5+(5) ).  

原理是一樣的,但是reverse直接替換掉了FM和LOOP的功能(依然要注意字符串本身長度的問題),而且這兩句其實也可以寫在一起,如下:

lv_str_out5 = reverse( reverse( lv_str_out5+(5) ) ).

方法三:

 DATA(lv_str_out3) = lv_str.
 DO.
   IF strlen( lv_str_out3 ) <= 5.
     EXIT.
   ENDIF.
   SHIFT lv_str_out3 BY 1 PLACES LEFT.
 ENDDO.  

代碼也易懂,就不停干掉最前面一位,直到符合我們的需求。

該代碼無需考慮字符串位數,干就完事了,缺點就是...如果字符串很長,那效率可能會稍微有點問題。

所以做了如下優化:

SHIFT lv_str_out4 BY strlen( lv_str_out4 ) - 5 PLACES LEFT.

OK , 這樣一來,我們只需要一行代碼就解決了問題,而且本以為如果字符串長度小於5會炸,結果實測並沒有。

看來shift的語法,如果by n 的n是負數,那么該語法會默認為0,什么都不做。

反觀str+n(m),如果n是負數,那么就會dump,如果n位后不足m位,也會dump,所以這語法就顯得不是很聰明的樣子。 

 

以上代碼均已通過測試。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM