Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

FIND ... REGEX replacing the first string between &...&

Former Member
0 Likes
4,023

Dear ABAP experts,

I'm quite desperate in a simply looking replacement function, where I need to replace a set of variables between & and & one after another. I have tried a whole bunch of regular expressions now, read through the SAP help and the SCN but didn't yet find the solution (although there were some helpful hints).

I'm using the SAP Standard report DEMO_REGEX_TOY to check the regular expression.

Search string is

a = &ATTRIB_02-VAL_CHAR& ) AND '&ATTRIB_01-VAL_CHAR&' OR &ATTRIB_04-VAL_CURR& xy

And I would like to get the highlighted ones, one after another:

a = &ATTRIB_02-VAL_CHAR& ) AND '&ATTRIB_01-VAL_CHAR&' OR &ATTRIB_04-VAL_CURR& xy

The regular expression that I'm using is

&ATTRIB_\d\d-.*&

I'm using the following statement to walk through the hitlist (yes there's some more coding above and below, but I omit it here for readability):

FIND FIRST OCCURRENCE OF
                REGEX '&ATTRIB_\d\d-.*&'
                IN cv_where_clause
                MATCH OFFSET lv_off
                MATCH LENGTH lv_len.

The REGEX now tries to return the longest possible match, so the result is:

a = &ATTRIB_02-VAL_CHAR& ) AND '&ATTRIB_01-VAL_CHAR&' OR &ATTRIB_04-VAL_CURR& xy

So here's my question:

I'm looking for a REGEX expression that returns only the first part, i.e.  &ATTRIB_02-VAL_CHAR&

a = &ATTRIB_02-VAL_CHAR& ) AND '&ATTRIB_01-VAL_CHAR&' OR &ATTRIB_04-VAL_CURR& xy

Any suggestions ... and solutions ... are warmly welcoem.

With the very best wishes,

   Florin


1 ACCEPTED SOLUTION
Read only

PeterJonker
Active Contributor
0 Likes
2,258

Only if the field length is Always the same (which it is in your sample, but maybe not in real wordl) the following would work

&ATTRIB_...........&

I guess that is too simple. You probably have different lengths.

4 REPLIES 4
Read only

PeterJonker
Active Contributor
0 Likes
2,259

Only if the field length is Always the same (which it is in your sample, but maybe not in real wordl) the following would work

&ATTRIB_...........&

I guess that is too simple. You probably have different lengths.

Read only

0 Likes
2,258

Hi Peter,

yes, that's true; there're of different length, as they are defined at runtime, respectivily can be maintained through customizing.

I think that I need to follow a two-step approach, i.e.

  1. Using a regex that finds the &ATTRIBxx- part
  2. Manually walk through the rest of the string, starting at the lv_off + lv_len position and find the next & character.

Working with Strings is not the homebase of ABAP/4

If there're more ideas, everyone is welcome to join the discussion!

With the best wishes

   Florin

Read only

0 Likes
2,258

Motivation

I was pretty convinced, that regular expressions are extremely powerful and this ... quite simple requirement ... should be somewhat easy to solved. However, it wasn't, but with the help of the REGEX toy I've found the correction expression now!

The trick is to define the characters between the first part &ATTRIB_nn- and the ending of the placeholder (ending with &) in a way that exclude any other &-characters. That way, the match cannot exceed the first occurrence of the delimiting character, i.e. &.

I have found two solutions:

(&(ATTRIB_\d\d)-([[:word:]]{1,})&)


(&(ATTRIB_\d\d)-([A-Z,0-9,_]{1,})&)

Submatches

The brackets () have no meaning, other than to deliver substrings of the match to prepared variables. When doing so, you already retrieve the full name of the placeholder and the left and right-hand part from the dash, i.e.

- submatch 1 = &ATTRIB_01-FIELDNAME&

- submatch 2 = ATTRIBT_01

- submatch 3 = FIELDNAME

So you can save an further statements like   lv_placeholder = searchstring+lv_len(lv_off).  etc.

Details

The [:word:] means the set of characters, without special characters. So ! ? * & ... are excluded.

The {1,} is extending the previous token [...] of the regular expression, saying: There must be at least one of such a kind, and then as many as you can find

The \d means: Any digit

Picture and Code

So I'm very happy that it did finally work out well.


       DATA: lv_placeholder                        TYPE STRING,
             lv_db_field                           TYPE STRING,
             lv_value_field                        TYPE STRING.

       CLEAR: lv_placeholder, lv_db_field, lv_value_field.

       DATA: lv_off                                TYPE I,
             lv_len                                TYPE I.

       FIND REGEX '(&(ATTRIB_\d\d)-([[:word:]]{1,})&)'
            IN cv_where_clause
            MATCH OFFSET lv_off MATCH LENGTH lv_len
            SUBMATCHES lv_placeholder lv_db_field lv_value_field
            RESPECTING CASE.
       IF sy-subrc <> 0.
          EXIT. "Nothing to do anymore
       ENDIF.

Replacement though is still a bit tricky, as you may change the source-string during replacements. That's the reason why I didn't chose to use MATCH RESULT lt_match_result.


Read only

0 Likes
2,258

Congratulatoions are in place here. Well done. It took some time but you got it.

It really can be complex those regular expressions. Again well done.