2

I currently have to a code in ABAP which contains a String that has multiple words that start with Capital letters/Uppercase and there is no space in-between.

I have to separate it into an internal table like this:

INPUT :

NameAgeAddress

OUTPUT :

Name

Age

Address
Suncatcher
  • 10,355
  • 10
  • 52
  • 90
Mick
  • 111
  • 3
  • 11

5 Answers5

5

Here is the shortest code I could find, which uses a regular expression combined with SPLIT:

SPLIT replace( val = 'NameAgeAddress' regex = `(?!^.)\u` with = ` $0` occ = 0 ) 
      AT ` ` 
      INTO TABLE itab.

So, replace converts 'NameAgeAddress' into 'Name Age Address' and SPLIT puts the 3 words into an internal table.

Details:

  • (?!^.) to say the next character to find (\u) should not be the first character
  • \u being any upper case letter
  • $0 to replace the found string ($0) by itself preceded with a space character
  • occ = 0 to replace all occurrences
Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
  • The best possible workaround for the idiom `SPLIT ... AT REGEX ... INTO TABLE ...` which is missing in ABAP. – rplantiko Apr 12 '19 at 18:53
1

Unfortunately, the SPLIT statement in ABAP does not allow a regex as separator expression. Therefore, we have to use progressive matching, which is a bit awkward in 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 ).

Just for comparison, the following statement would do the job in Perl:

my $input = "NameAgeAddress";
my @output = split /(?=[A-Z])/, $input; 
# gives @output = ('Name','Age','Address') 
rplantiko
  • 2,698
  • 1
  • 22
  • 21
  • 2
    A very, very, very complex solution for a simple issue. The Germans say "warum einfach, wenn es auch kompliziert geht.". – Jagger Apr 12 '19 at 17:01
  • @Jagger OP has marked this answer as accepted. In German, there is another saying: "Ätschi!" ;-) – rplantiko Apr 15 '19 at 11:39
  • Don't know why, must be an oversight. ;) Clearly Sandra's answer should be mark as accepted. – Jagger Apr 15 '19 at 11:47
1

It is easy with using regular expressions. The solution could look like this.

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.
Jagger
  • 10,350
  • 9
  • 51
  • 93
1

For when regular expressions are just overkill and plain old ABAP will do:

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.
Gert Beukema
  • 2,510
  • 1
  • 17
  • 18
1

If you do not want to use or cannot use Regex, here another solution:

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.
futu
  • 868
  • 6
  • 12