如何用大写字母分隔字符串?
How to separate a string by Capital Letter?
我目前必须在 ABAP 中编写一个代码,其中包含一个字符串,该字符串具有多个以大写 letters/Uppercase 开头的单词,中间没有 space。
我必须把它分成一个内部 table 像这样:
输入:
NameAgeAddress
输出:
Name
Age
Address
不幸的是,ABAP 中的 SPLIT
语句不允许将正则表达式作为分隔符表达式。所以,我们不得不使用渐进式匹配,在ABAP中有点尴尬:
report zz_test_split_capital.
parameters: p_input type string default 'NameAgeAddress' lower case.
data: output type stringtab,
off type i,
moff type i,
mlen type i.
while off < strlen( p_input ).
find regex '[A-Z][^A-Z]*'
in section offset off of p_input
match offset moff match length mlen.
if sy-subrc eq 0.
append substring( val = p_input off = moff len = mlen ) to output.
off = moff + mlen.
else.
exit.
endif.
endwhile.
cl_demo_output=>display_data( output ).
为了比较,下面的语句可以在 Perl 中完成:
my $input = "NameAgeAddress";
my @output = split /(?=[A-Z])/, $input;
# gives @output = ('Name','Age','Address')
使用正则表达式很容易。解决方案可能如下所示。
REPORT ZZZ.
DATA: g_string TYPE string VALUE `NameAgeAddress`.
DATA(gcl_regex) = NEW cl_abap_regex( pattern = `[A-Z]{1}[a-z]+` ).
DATA(gcl_matcher) = gcl_regex->create_matcher( text = g_string ).
WHILE gcl_matcher->find_next( ).
DATA(g_match_result) = gcl_matcher->get_match( ).
WRITE / g_string+g_match_result-offset(g_match_result-length).
ENDWHILE.
这是我能找到的最短的代码,它使用 regular expression combined with SPLIT
:
SPLIT replace( val = 'NameAgeAddress' regex = `(?!^.)\u` with = ` [=10=]` occ = 0 )
AT ` `
INTO TABLE itab.
因此,replace
将 'NameAgeAddress' 转换为 'Name Age Address',SPLIT
将 3 个单词放入内部 table。
详情:
(?!^.)
表示下一个要查找的字符(\u)不应该是第一个字符
\u
是任何大写字母
[=16=]
用 space 字符 替换找到的字符串 ($0)
occ = 0
替换所有出现的地方
因为当正则表达式只是矫枉过正而普通的旧 ABAP 可以做到时:
DATA(str) = 'NameAgeAddress'.
IF str CA sy-abcde.
DATA(off) = 0.
DO.
data(tailstart) = off + 1.
IF str+tailstart CA sy-abcde.
DATA(len) = sy-fdpos + 1.
WRITE: / str+off(len).
add len to off.
ELSE.
EXIT.
ENDIF.
ENDDO.
write / str+off.
ENDIF.
如果您不想使用或不能使用正则表达式,这里有另一个解决方案:
DATA: lf_input TYPE string VALUE 'NameAgeAddress',
lf_offset TYPE i,
lf_current_letter TYPE char1,
lf_letter_in_capital TYPE char1,
lf_word TYPE string,
lt_word LIKE TABLE OF lf_word.
DO strlen( lf_input ) TIMES.
lf_offset = sy-index - 1.
lf_current_letter = lf_input+lf_offset(1).
lf_letter_in_capital = to_upper( lf_current_letter ).
IF lf_current_letter = lf_letter_in_capital.
APPEND INITIAL LINE TO lt_word ASSIGNING FIELD-SYMBOL(<ls_word>).
ENDIF.
IF <ls_word> IS ASSIGNED. "if input string does not start with capital letter
<ls_word> = <ls_word> && lf_current_letter.
ENDIF.
ENDDO.
我目前必须在 ABAP 中编写一个代码,其中包含一个字符串,该字符串具有多个以大写 letters/Uppercase 开头的单词,中间没有 space。
我必须把它分成一个内部 table 像这样:
输入:
NameAgeAddress
输出:
Name
Age
Address
不幸的是,ABAP 中的 SPLIT
语句不允许将正则表达式作为分隔符表达式。所以,我们不得不使用渐进式匹配,在ABAP中有点尴尬:
report zz_test_split_capital.
parameters: p_input type string default 'NameAgeAddress' lower case.
data: output type stringtab,
off type i,
moff type i,
mlen type i.
while off < strlen( p_input ).
find regex '[A-Z][^A-Z]*'
in section offset off of p_input
match offset moff match length mlen.
if sy-subrc eq 0.
append substring( val = p_input off = moff len = mlen ) to output.
off = moff + mlen.
else.
exit.
endif.
endwhile.
cl_demo_output=>display_data( output ).
为了比较,下面的语句可以在 Perl 中完成:
my $input = "NameAgeAddress";
my @output = split /(?=[A-Z])/, $input;
# gives @output = ('Name','Age','Address')
使用正则表达式很容易。解决方案可能如下所示。
REPORT ZZZ.
DATA: g_string TYPE string VALUE `NameAgeAddress`.
DATA(gcl_regex) = NEW cl_abap_regex( pattern = `[A-Z]{1}[a-z]+` ).
DATA(gcl_matcher) = gcl_regex->create_matcher( text = g_string ).
WHILE gcl_matcher->find_next( ).
DATA(g_match_result) = gcl_matcher->get_match( ).
WRITE / g_string+g_match_result-offset(g_match_result-length).
ENDWHILE.
这是我能找到的最短的代码,它使用 regular expression combined with SPLIT
:
SPLIT replace( val = 'NameAgeAddress' regex = `(?!^.)\u` with = ` [=10=]` occ = 0 )
AT ` `
INTO TABLE itab.
因此,replace
将 'NameAgeAddress' 转换为 'Name Age Address',SPLIT
将 3 个单词放入内部 table。
详情:
(?!^.)
表示下一个要查找的字符(\u)不应该是第一个字符\u
是任何大写字母[=16=]
用 space 字符 替换找到的字符串 ($0)
occ = 0
替换所有出现的地方
因为当正则表达式只是矫枉过正而普通的旧 ABAP 可以做到时:
DATA(str) = 'NameAgeAddress'.
IF str CA sy-abcde.
DATA(off) = 0.
DO.
data(tailstart) = off + 1.
IF str+tailstart CA sy-abcde.
DATA(len) = sy-fdpos + 1.
WRITE: / str+off(len).
add len to off.
ELSE.
EXIT.
ENDIF.
ENDDO.
write / str+off.
ENDIF.
如果您不想使用或不能使用正则表达式,这里有另一个解决方案:
DATA: lf_input TYPE string VALUE 'NameAgeAddress',
lf_offset TYPE i,
lf_current_letter TYPE char1,
lf_letter_in_capital TYPE char1,
lf_word TYPE string,
lt_word LIKE TABLE OF lf_word.
DO strlen( lf_input ) TIMES.
lf_offset = sy-index - 1.
lf_current_letter = lf_input+lf_offset(1).
lf_letter_in_capital = to_upper( lf_current_letter ).
IF lf_current_letter = lf_letter_in_capital.
APPEND INITIAL LINE TO lt_word ASSIGNING FIELD-SYMBOL(<ls_word>).
ENDIF.
IF <ls_word> IS ASSIGNED. "if input string does not start with capital letter
<ls_word> = <ls_word> && lf_current_letter.
ENDIF.
ENDDO.