Vorsicht mit der Ende-Zusicherung in ABAP

44 views
Skip to first unread message

Rüdiger

unread,
Jan 29, 2010, 9:23:17 AM1/29/10
to BSP-Praxis
Die folgenden Modultests zeigen die Problematik der Ende-Zusicherung
'$' bei der Verwendung von regulären Ausdrücken und dem CP/NP-Operator
in ABAP.

Der erste Test zeigt, dass für Strings scheinbar schliessende
Leerzeichen ignoriert werden:

method test_end_string.
data: lv_string type string value '1234 '.
find regex '4$' in lv_string.
assert_subrc( act = sy-subrc
msg = `Stringende mit '4' muss erkannt werden` ).
endmethod.

Die Erklärung ist einfach: Schon die Initialisierung des Strings mit
VALUE schneidet den Leerraum ab. Die 4 steht daher wirklich an der
letzten Position des Strings. Dies entspricht der Konvertierungsregel
für MOVE (Typ C vom Literal nach String entfernt schliessende
Leerzeichen).

Man muss sich also schon ein bisschen anstrengen, um an den Schluss
des Strings noch Leerzeichen zu bekommen. Es ist jedoch möglich und
kommt in der Praxis auch vor. Im nächsten Test baue ich einen String
künstlich mit schliessenden Leerzeichen auf. Der Ausdruck '4$' bringt
erwartungsgemäss keinen Treffer:

method test_end_string_trailing_blank.
data: lv_string type string.
concatenate '1234' ' ' into lv_string respecting blanks.
find regex '4$' in lv_string.
if sy-subrc eq 0.
fail( 'Stringende mit 4 darf nicht erkannt werden (schliessende
Leerzeichen!)' ).
endif.
endmethod.

Bis jetzt könnte man sagen, verlief alles fast nach dem Prinzip der
kleinsten Überraschung. Doch der folgende Test ist wohl nicht mehr
das, was man erwarten würde: Wir geben einem Typ C-Feld den Wert
'1234' und testen, dass die 4 nicht als am Schluss stehend betrachtet
wird. Das ist so, weil bei Typ C-Feldern fester Länge, ganz anders als
Strings, der schliessende Leerraum bis zum definierten Ende eine Rolle
spielt!

method test_end_char10.
data: lv_char10 type char10 value '1234'.
find regex '4$' in lv_char10.
if sy-subrc eq 0.
fail( `Feld-Ende mit '4' darf nicht erkannt werden!` ).
endif.
endmethod.

Man muss also, um die 4 in diesem Fall zu erkennen, mit dem regulären
Ausdruck '4\s*$' statt '4$' arbeiten, um den Weissraum explizit zu
erwähnen.

Wieder anders sieht es für den klassischen Operator NP (contains not
pattern) aus: Er betrachtet auch im CHAR10-Feld die 4 wiederum als am
Ende stehend:

method test_standard_end_pattern.
data: lv_char10 type char10 value '1234 '.
if lv_char10 np '*4'.
fail( `Feld-Ende mit '4' muss erkannt werden` ).
endif.
endmethod.

Das sind verwirrende Unterschiede in der ABAP-Implementierung von
Pattern-Suche, die man einfach kennen muss. Ändern lässt sich das SAP-
seitig mit Sicherheit nicht mehr.

Hier der gesamte Report zum Nachvollziehen im eigenen SAP-System
(Tests mit Programm -> Testen -> Modultest) oder einfach mit Strg+Shift
+F10 ausführen.


*&---------------------------------------------------------------------
*
*& Report ZZ_TEST_REGEX_TERMINALS
*&
*&---------------------------------------------------------------------
*
*& Ein paar Lerntests über reguläre Ausdrücke
*&---------------------------------------------------------------------
*

report zz_test_regex_terminals.

*
class lcl_test definition for testing " #AU Risk_Level Harmless
inheriting from cl_aunit_assert. " #AU Duration Short

private section.
methods:
test_end_string for testing,
test_end_string_trailing_blank for testing,
test_end_char10 for testing,
test_standard_end_pattern for testing.

endclass. "lcl_test DEFINITION

*
class lcl_test implementation.
method test_end_string.
data: lv_string type string value '1234 '. "Nur scheinbar
Blanks am Schluss
find regex '4$' in lv_string.
assert_subrc( act = sy-subrc
msg = `Stringende mit '4' muss erkannt werden` ).
endmethod.
method test_end_string_trailing_blank.
data: lv_string type string.
concatenate '1234' ' ' into lv_string respecting blanks.
find regex '4$' in lv_string.
if sy-subrc eq 0.
fail( 'Stringende mit 4 darf nicht erkannt werden (schliessende
Leerzeichen!)' ).
endif.
endmethod.
method test_end_char10.
data: lv_char10 type char10 value '1234'.
find regex '4$' in lv_char10.
if sy-subrc eq 0.
fail( `Feld-Ende mit '4' darf nicht erkannt werden!` ).
endif.
endmethod.
method test_standard_end_pattern.
data: lv_char10 type char10 value '1234 '.
if lv_char10 np '*4'.
fail( `Feld-Ende mit '4' muss erkannt werden` ).
endif.
endmethod.
endclass. "lcl_test IMPLEMENTATION

Reply all
Reply to author
Forward
0 new messages