Eine der häufigsten Anforderung in nahezu jeder Programmiersprache ist der Vergleich zweier Zeichenketten. ABAP bietet dazu eine Reihe von Vergleichsoperatoren an. Die Verwendung kann jedoch tückisch sein, wie ich neulich wieder einmal feststellen musste. Das hat mich dazu angeregt, ein kleines Programm zu schreiben, welches die Verwendung und natürlich die Ergebnisse der vielen Vergleichsoperatoren aufzeigt.
Problem
Es soll das Vorkommen einer Zeichenkette in einer anderen Zeichenkette geprüft werden. Neben der zu suchenden Zeichenkette soll aber keine weitere enthalten sein.
Ein Beispiel. Liest man den Anwenderstatus eines beliebigen Objektes (Auftrag, Lieferschein etc.) aus, so erhält man diesen als String zurück. Es soll geprüft werden, ob ein bestimmter Status gesetzt ist. Es darf aber kein weiterer Status gesetzt sein. Die gesuchte Zeichenkette ist 'INIT', die zu durchsuchende Zeichenkette ist 'INIT DIBE DIER '.
Nun könnte man annehmen, dass im Falle des Status INIT die zu durchsuchende Zeichenkette 'INIT ' enthält. Durch kopieren der Zeichenkette in eine andere Variable bzw. durch das entfernen der Leerzeichen wäre ein Vergleich problemos möglich. Es lässt sich aber auch eleganter lösen.
Lösung
Der Vergleichsoperator CP (covers pattern) leistet hier gute Dienste. Normalerweise wird der Operator verwendet, um per Wildcard zu suchen, beispielsweise nach einer Zeichenkette, die mit'IN' (IN*) beginnt. Wir verwenden hier aber nur den zu suchenden String, ohne Wildcards wie * oder +.
Andere Vergleichsoperatoren wie CO (contains only) scheitern, da in der zu durchsuchenden Zeichenkette auch Leerzeichen vorkommen. CA (contains any) liefern auch dann einen Erfolg, wenn weitere Zeichenketten vorhanden sind. Außerdem prüfen diese Vergleichsoperatoren nicht mit der gesamten Suchzeichenkette, sondern prüfen, ob ein Zeichen der gesuchten Zeichenkette im Suchstring enthalten ist. Somit ist folgender Ausdruck ebenfalls war:
If 'INIT' CA 'NNIT'.
Beispielreport
Der Report Z_TEST_STRING zeigt die Wirkung der unterschiedlichen Vergleichsoperatoren
*&---------------------------------------------------------------------*
*& Report Z_TEST_STRING
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT z_test_string.
DATA: text(50) TYPE c VALUE 'INIT '.
DATA: text1(50) TYPE c VALUE 'INIT DIBE DIER '.
DATA: text2(50) TYPE c VALUE 'INIT NNIT '.
DATA: text3(50) TYPE c VALUE ' NNIT '.
DATA: text4(50) TYPE c VALUE 'DIBE DIER '.
DATA: text5(50) TYPE c VALUE 'ABDC '.
DATA: search(4) TYPE c VALUE 'INIT'.
PERFORM do_write USING 'Text' 'Search' 'OP' 'Found'.
WRITE /5 sy-uline(66).
* CONTAINS ONLY
PERFORM check_co USING text search.
PERFORM check_co USING text1 search.
PERFORM check_co USING text2 search.
PERFORM check_co USING text3 search.
PERFORM check_co USING text4 search.
PERFORM check_co USING text5 search.
WRITE /5 sy-uline(66).
* CONTAINS NOT ONLY
PERFORM check_cn USING text search.
PERFORM check_cn USING text1 search.
PERFORM check_cn USING text2 search.
PERFORM check_cn USING text3 search.
PERFORM check_cn USING text4 search.
PERFORM check_cn USING text5 search.
WRITE /5 sy-uline(66).
* CONTAINS ANY
PERFORM check_ca USING text search.
PERFORM check_ca USING text1 search.
PERFORM check_ca USING text2 search.
PERFORM check_ca USING text3 search.
PERFORM check_ca USING text4 search.
PERFORM check_ca USING text5 search.
WRITE /5 sy-uline(66).
* CONTAINS NOT ANY
PERFORM check_na USING text search.
PERFORM check_na USING text1 search.
PERFORM check_na USING text2 search.
PERFORM check_na USING text3 search.
PERFORM check_na USING text4 search.
PERFORM check_na USING text5 search.
WRITE /5 sy-uline(66).
* CONTAINS STRING
PERFORM check_cs USING text search.
PERFORM check_cs USING text1 search.
PERFORM check_cs USING text2 search.
PERFORM check_cs USING text3 search.
PERFORM check_cs USING text4 search.
PERFORM check_cs USING text5 search.
WRITE /5 sy-uline(66).
* CONTAINS NO STRING
PERFORM check_ns USING text search.
PERFORM check_ns USING text1 search.
PERFORM check_ns USING text2 search.
PERFORM check_ns USING text3 search.
PERFORM check_ns USING text4 search.
PERFORM check_ns USING text5 search.
WRITE /5 sy-uline(66).
* COVERS PATTERN
PERFORM check_cp USING text search.
PERFORM check_cp USING text1 search.
PERFORM check_cp USING text2 search.
PERFORM check_cp USING text3 search.
PERFORM check_cp USING text4 search.
PERFORM check_cp USING text5 search.
WRITE /5 sy-uline(66).
* NO PATTERN
PERFORM check_np USING text search.
PERFORM check_np USING text1 search.
PERFORM check_np USING text2 search.
PERFORM check_np USING text3 search.
PERFORM check_np USING text4 search.
PERFORM check_np USING text5 search.
WRITE /5 sy-uline(66).
*---------------------------------------
* Contains only char
*---------------------------------------
FORM check_co USING iv_text TYPE char50
iv_search TYPE char4.
DATA: operator(4) TYPE c.
DATA: found(1) TYPE c.
operator = 'CO'.
IF iv_text CO iv_search.
found = 'X'.
ENDIF.
PERFORM do_write USING iv_text iv_search operator found.
ENDFORM.
*---------------------------------------
* contains not char
*---------------------------------------
FORM check_cn USING iv_text TYPE char50
iv_search TYPE char4.
DATA: operator(4) TYPE c.
DATA: found(1) TYPE c.
operator = 'CN'.
IF iv_text CN iv_search.
found = 'X'.
ENDIF.
PERFORM do_write USING iv_text iv_search operator found.
ENDFORM.
*---------------------------------------
* Contains any char
*---------------------------------------
FORM check_ca USING iv_text TYPE char50
iv_search TYPE char4.
DATA: operator(4) TYPE c.
DATA: found(1) TYPE c.
operator = 'CA'.
IF iv_text CA iv_search.
found = 'X'.
ENDIF.
PERFORM do_write USING iv_text iv_search operator found.
ENDFORM.
*---------------------------------------
* contains not any char
*---------------------------------------
FORM check_na USING iv_text TYPE char50
iv_search TYPE char4.
DATA: operator(4) TYPE c.
DATA: found(1) TYPE c.
operator = 'NA'.
IF iv_text NA iv_search.
found = 'X'.
ENDIF.
PERFORM do_write USING iv_text iv_search operator found.
ENDFORM.
*---------------------------------------
* Contains string
*---------------------------------------
FORM check_cs USING iv_text TYPE char50
iv_search TYPE char4.
DATA: operator(4) TYPE c.
DATA: found(1) TYPE c.
operator = 'CS'.
IF iv_text CS iv_search.
found = 'X'.
ENDIF.
PERFORM do_write USING iv_text iv_search operator found.
ENDFORM.
*---------------------------------------
* contains not string
*---------------------------------------
FORM check_ns USING iv_text TYPE char50
iv_search TYPE char4.
DATA: operator(4) TYPE c.
DATA: found(1) TYPE c.
operator = 'NS'.
IF iv_text NS iv_search.
found = 'X'.
ENDIF.
PERFORM do_write USING iv_text iv_search operator found.
ENDFORM.
*---------------------------------------
* cover pattern
*---------------------------------------
FORM check_cp USING iv_text TYPE char50
iv_search TYPE char4.
DATA: operator(4) TYPE c.
DATA: found(1) TYPE c.
operator = 'CP'.
IF iv_text CP iv_search.
found = 'X'.
ENDIF.
PERFORM do_write USING iv_text iv_search operator found.
ENDFORM.
*---------------------------------------
* cover not pattern
*---------------------------------------
FORM check_np USING iv_text TYPE char50
iv_search TYPE char4.
DATA: operator(4) TYPE c.
DATA: found(1) TYPE c.
operator = 'NP'.
IF iv_text NP iv_search.
found = 'X'.
ENDIF.
PERFORM do_write USING iv_text iv_search operator found.
ENDFORM.
*---------------------------------------
* output
*---------------------------------------
FORM do_write USING iv_text TYPE c
iv_search TYPE c
iv_operator TYPE c
iv_found TYPE c.
WRITE: /5 sy-vline,
iv_search ,
15 sy-vline,
iv_text,
55 sy-vline,
iv_operator,
60 sy-vline,
62 iv_found,
70 sy-vline.
ENDFORM.