眾所周知,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,所以這語法就顯得不是很聰明的樣子。
以上代碼均已通過測試。
