forked from SAP-samples/abap-cheat-sheets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
zcl_demo_abap_string_proc.clas.abap
1755 lines (1393 loc) · 67.3 KB
/
zcl_demo_abap_string_proc.clas.abap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
***********************************************************************
*
* ABAP cheat sheet: String processing
*
* -------------------------- PURPOSE ----------------------------------
* - Example to demonstrate various syntactical options for processing
* character strings.
* - Topics covered: Creating strings and assigning values, chaining strings,
* string templates, concatenating/splitting/modifying strings, searching
* and replacing, regular expressions
*
* ----------------------- GETTING STARTED -----------------------------
* - Open the class with the ABAP Development Tools (ADT).
* - Choose F9 to run the class.
* - Check the console output.
* - To understand the context and the ABAP syntax used, refer to the
* notes included in the class as comments or refer to the respective
* topic in the ABAP Keyword Documentation.
* - Due to the amount of console output, the examples contain numbers
* (e.g. 1) ..., 2) ..., 3) ...) for the individual example sections.
* Also, the variable name is displayed in most cases. So to find
* the relevant output in the console easier and faster, just search
* for the number/variable name in the console (CTRL+F in the console)
* or use the debugger.
*
* ----------------------------- NOTE -----------------------------------
* The code presented in this class is intended only to support the ABAP
* cheat sheets. It is not intended for direct use in a production system
* environment. The code examples in the ABAP cheat sheets are primarily
* intended to provide a better explanation and visualization of the
* syntax and semantics of ABAP statements, not to solve concrete
* programming tasks. For production application programs, you should
* always work out your own solution for each individual case. There is
* no guarantee for the correctness or completeness of the code.
* Furthermore, there is no legal responsibility or liability for any
* errors or their consequences that may occur when using the the example
* code.
*
***********************************************************************
"! <p class="shorttext synchronized">ABAP cheat sheet: String processing</p>
"! Example to demonstrate string processing.<br>Choose F9 in ADT to run the class.
CLASS zcl_demo_abap_string_proc DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES: if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_demo_abap_string_proc IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA(output) = NEW zcl_demo_abap_display( out ).
output->display( `ABAP Cheat Sheet Example: String Processing` ).
output->display( `1) Creating Strings and Assigning Values` ).
"Data object declarations providing default values
DATA: flag TYPE c LENGTH 1 VALUE 'X', "Single quotes
str_a1 TYPE string VALUE `Hallo, how are you?`. "Backquotes
DATA: char_a1 TYPE c LENGTH 5,
str_a2 TYPE string,
str_a3 LIKE str_a2.
"Examples for type n
DATA zip_code TYPE n LENGTH 5 VALUE '12345'.
DATA isbn_number TYPE n LENGTH 13 VALUE '1234567890123'.
"Value assignments to existing data objects
char_a1 = 'ab123'.
str_a2 = `<p>Hallo!</p>`.
"Escaping a backquote using another backquote
str_a3 = `This is a backquote: ``.`.
"If possible, avoid unnecessary type conversion; in principle,
"every convertible type can be specified
"Assigning a fixed-length string to a variable-length string.
str_a2 = 'abc'.
DATA str_a4 TYPE string VALUE 'X'. "Type c length 1
DATA str_a5 TYPE string VALUE -1. "Type i
"Inline declaration: data object declaration and
"value assignment
"Data type is automatically derived
DATA(char_a2) = 'abcd'. "Type c length 4
DATA(str_a6) = `efgh`. "Type string
"Note: Variable is of type c length 4. Characters are truncated.
char_a2 = 'ijklmnopq'.
"Treating trailing blanks
DATA(char_a3) = 'ab '.
DATA(str_a7) = `cdefgh`.
str_a7 = char_a3. "Trailing blanks are not respected.
"Excursion: Chaining strings
"Note the conversion result of str_a5 above (i to string)
DATA(str_a8) = str_a4 && ` ` && str_a5 && `!`.
output->display( input = str_a3 name = `str_a3` ).
output->display( input = char_a2 name = `char_a2` ).
output->display( input = str_a7 name = `str_a7` ).
output->display( input = str_a8 name = `str_a8` ).
**********************************************************************
output->next_section( `2) Chaining Strings` ).
DATA(str_b1) = `Hallo`.
DATA(str_b2) = `how`.
DATA(str_b3) = `are`.
"Chaining using && operator
DATA(str_b4) = str_b1 && ` ` && sy-uname && `, ` && str_b2 && ` ` && str_b3 && ` you?`.
"Chaining only character literals of the same type using & operator
"Note: Such a combination of literals is possible up to 255 chars.
DATA(char_b1) = 'AB' & 'AP '. "Trailing blanks are ignored
DATA(str_b5) = `AB` & `AP `.
output->display( input = str_b4 name = `str_b4` ).
output->display( input = char_b1 name = `char_b1` ).
**********************************************************************
output->next_section( `3a) String Templates (1): Constructing Strings` ).
"The expression must be convertible to a string. A blank (not
"within the curly brackets) means a blank in the resulting string.
DATA(str_c1) = `Hallo`. "String created with backquotes
DATA(str_c2) = `how`. "Strings created with pipes
DATA(str_c3) = `are`.
DATA(str_c4) = |{ str_c1 } { sy-uname }, | &&
|{ str_c2 } { str_c3 } you?|.
**********************************************************************
output->next_section( `3b) String Templates (2): Control Characters` ).
"Interpretation of character combinations as control characters
"\n interpreted as a line break
DATA(str_c5) = |{ str_c1 }\n{ sy-uname },| &&
|\n{ str_c2 }\n{ str_c3 }\nyou?|.
output->display( input = str_c4 name = `str_c4` ).
output->display( input = str_c5 name = `str_c5` ).
"Excursion: Class CL_ABAP_CHAR_UTILITIES provides attributes and methods as utilities for string processing.
"See the class documentation.
"The following examples demonstrate that attributes that contain control characters can be replaced by
"a representation of control characters in a string template.
DATA(str_c6) = |{ str_c1 }{ cl_abap_char_utilities=>newline }{ sy-uname }|.
DATA(str_c7) = |{ str_c1 }\n{ sy-uname }|.
DATA(str_c8) = |{ str_c1 }{ cl_abap_char_utilities=>horizontal_tab }{ sy-uname }|.
DATA(str_c9) = |{ str_c1 }\t{ sy-uname }|.
DATA(str_c10) = |{ str_c1 }{ cl_abap_char_utilities=>cr_lf }{ sy-uname }|.
DATA(str_c11) = |{ str_c1 }\r\n{ sy-uname }|.
ASSERT str_c10 = str_c11.
output->display( input = str_c6 name = `str_c6` ).
output->display( input = str_c7 name = `str_c7` ).
output->display( input = str_c8 name = `str_c8` ).
output->display( input = str_c9 name = `str_c9` ).
**********************************************************************
output->next_section( `4) String Templates (3): Formatting Options` ).
"Time, date
DATA(str_d1) =
|Date: { cl_abap_context_info=>get_system_date( ) DATE = USER }\n| &&
|Time: { cl_abap_context_info=>get_system_time( ) TIME = ISO }\n| &&
|Timestamp: { utclong_current( ) TIMESTAMP = SPACE }|.
"Upper, lower case
DATA(str_d2) = |AbCdEfG|.
DATA(str_d3) = |{ str_d2 CASE = LOWER }|.
DATA(str_d4) = |{ str_d2 CASE = UPPER }|.
"Width and alignment
DATA(str_d5) = |{ 'Left' WIDTH = 20 ALIGN = LEFT }<---|.
DATA(str_d6) = |{ 'Center' WIDTH = 20 ALIGN = CENTER }<---|.
DATA(str_d7) = |{ 'Right' WIDTH = 20 ALIGN = RIGHT }<---|.
DATA(str_d8) = |{ 'Left' WIDTH = 20 ALIGN = LEFT PAD = '.' }<---|.
DATA(str_d9) = |{ 'Center' WIDTH = 20 ALIGN = CENTER PAD = '.' }<---|.
DATA(str_d10) = |{ 'Right' WIDTH = 20 ALIGN = RIGHT PAD = '.' }<---|.
"Numbers
DATA(str_d11) = |{ - 2 / 3 DECIMALS = 3 }, {
CONV decfloat34( - 2 / 3 ) DECIMALS = 3 }, {
CONV f( - 2 / 3 ) DECIMALS = 3 }|.
"Escaping \|{} in string templates
DATA(str_d14) = |\\ \| \{ \}|.
output->display( input = str_d1 name = `str_d1` ).
output->display( input = str_d3 name = `str_d3` ).
output->display( input = str_d4 name = `str_d4` ).
output->display( input = str_d5 name = `str_d5` ).
output->display( input = str_d6 name = `str_d6` ).
output->display( input = str_d7 name = `str_d7` ).
output->display( input = str_d8 name = `str_d8` ).
output->display( input = str_d9 name = `str_d9` ).
output->display( input = str_d10 name = `str_d10` ).
output->display( input = str_d11 name = `str_d11` ).
output->display( input = str_d14 name = `str_d14` ).
**********************************************************************
output->next_section( `5) Determining the Length of Strings` ).
DATA(str_e1) = `abc def ghi `.
DATA(char_e1) = 'abc def ghi '.
"strlen
"Result depends on the type of the data object
"Fixed-length string ignores trailing blanks
DATA(length_e1) = strlen( str_e1 ).
DATA(length_e2) = strlen( char_e1 ).
"numofchar
"To exclude trailing blanks in any case.
DATA(length_e3) = numofchar( str_e1 ).
DATA(length_e4) = numofchar( char_e1 ).
"Excursion:
"To emphasizes modern, expression-enabled ABAP, the expression
"with the string function can be placed directly in the DO
"statement instead of having an extra variable.
DATA(str_e3) = `abcde`.
DATA(length_e5) = strlen( str_e3 ).
DATA(int_e1) = 0.
DO length_e5 TIMES.
int_e1 += 1.
ENDDO.
DATA(int_e2) = 0.
DO strlen( str_e3 ) TIMES.
int_e2 += 1.
ENDDO.
output->display( input = length_e1 name = `length_e1` ).
output->display( input = length_e2 name = `length_e2` ).
output->display( input = length_e3 name = `length_e3` ).
output->display( input = length_e4 name = `length_e4` ).
output->display( input = int_e1 name = `int_e1` ).
output->display( input = int_e2 name = `int_e2` ).
**********************************************************************
output->next_section( `6) Concatenating Strings` ).
DATA(str_f1) = `Hallo`.
DATA(str_f2) = `world`.
"Concatenation using && operator and string templates
DATA(str_f3) = str_f1 && str_f2.
DATA(str_f4) = str_f1 && ` ` && str_f2.
DATA(str_f5) = |{ str_f1 } { str_f2 }|.
"CONCATENATE statements
CONCATENATE str_f1 str_f2 INTO DATA(str_f6).
"Adding a separation sign using the addition SEPARATED BY
CONCATENATE str_f1 str_f2 INTO DATA(str_f7) SEPARATED BY ` `.
CONCATENATE str_f1 str_f2 INTO DATA(str_f8) SEPARATED BY `#`.
DATA(char_f1) = '2 trailing blanks: '.
DATA(char_f2) = '3 trailing blanks: '.
DATA(char_f3) = '<-'.
"Keeping trailing blanks in the result when concatenating
"fixed-length strings. The ones of variable-length strings are
"respected by default
CONCATENATE char_f1 char_f2 char_f3
INTO DATA(char_f4) RESPECTING BLANKS.
"Trailing blanks are ignored
CONCATENATE char_f1 char_f2 char_f3 INTO DATA(char_f5).
"Example use case: Concatenating smaller text fragments
"sequentially into a longer character sequence.
DATA: itab_g TYPE TABLE OF string,
alphabet1 TYPE string.
itab_g = VALUE #( ( `abc` ) ( `def` ) ( `ghi` ) ).
LOOP AT itab_g ASSIGNING FIELD-SYMBOL(<abc>).
alphabet1 = alphabet1 && <abc>.
"Alternative:
"CONCATENATE alphabet <abc> INTO alphabet.
ENDLOOP.
"Avoiding loops if your use case is to concatenate lines of an
"internal table into a string in one go
CONCATENATE LINES OF itab_g INTO DATA(alphabet2).
""Adding a separation sign using the addition SEPARATED BY
CONCATENATE LINES OF itab_g INTO DATA(alphabet3)
SEPARATED BY ` `.
"String function concat_lines_of
DATA(alphabet4) = concat_lines_of( table = itab_g ).
"sep parameter specifying the separation sign
DATA(alphabet5) = concat_lines_of( table = itab_g sep = `,` ).
output->display( input = str_f3 name = `str_f3` ).
output->display( input = str_f4 name = `str_f4` ).
output->display( input = str_f5 name = `str_f5` ).
output->display( input = str_f6 name = `str_f6` ).
output->display( input = str_f7 name = `str_f7` ).
output->display( input = str_f8 name = `str_f8` ).
output->display( input = char_f4 name = `char_f4` ).
output->display( input = char_f5 name = `char_f5` ).
output->display( input = alphabet1 name = `alphabet1` ).
output->display( input = alphabet2 name = `alphabet2` ).
output->display( input = alphabet3 name = `alphabet3` ).
output->display( input = alphabet4 name = `alphabet4` ).
output->display( input = alphabet5 name = `alphabet5` ).
**********************************************************************
output->next_section( `7) Splitting Strings` ).
DATA(str_g1) = `Hallo,world,12345`.
SPLIT str_g1 AT `,` INTO DATA(str_g2) DATA(str_g3) DATA(str_g4).
"Less data objects than possible splittings
SPLIT str_g1 AT `,` INTO DATA(str_g5) DATA(str_g6).
"Splitting string into an internal table
DATA itab_g1 TYPE TABLE OF string.
SPLIT str_g1 AT ',' INTO TABLE itab_g1.
"Getting the value of a specific segment
DATA(str_g7) = segment( val = str_g1 index = 2 sep = `,` ).
"Example with segment
"A string is split and the values of segments are retrieved. Here,
"all segments are retrieved and inserted into an internal table
"using a DO loop. If you specify an empty string, an exception of
"the class CX_SY_STRG_PAR_VAL is raised. This is true for this
"example since the DO loop inevitably runs into the error because
"of not specifying an appropriate number of loops. Note that
"if the index parameter of the segment function is positive, the
"occurrences are counted from the left. If index is negative, the
"occurrences are counted from the right.
DATA itab_g2 TYPE TABLE OF string.
DO.
TRY.
DATA(str_g8) = segment( val = str_g1
index = sy-index
sep = `,` ).
APPEND |Segment value: '{ str_g8 }' | &&
|Segment index: '{ sy-index }'| TO itab_g2.
CATCH cx_sy_strg_par_val.
DATA(seg_nom) = |There are { sy-index - 1 } | &&
|segments in the string.|.
EXIT.
ENDTRY.
ENDDO.
output->display( input = str_g2 name = `str_g2` ).
output->display( input = str_g3 name = `str_g3` ).
output->display( input = str_g4 name = `str_g4` ).
output->display( input = str_g5 name = `str_g5` ).
output->display( input = str_g6 name = `str_g6` ).
output->display( input = itab_g1 name = `itab_g1` ).
output->display( input = str_g7 name = `str_g7` ).
output->display( input = str_g8 name = `str_g8` ).
output->display( input = itab_g2 name = `itab_g2` ).
output->display( input = seg_nom name = `seg_nom` ).
**********************************************************************
output->next_section( `Modifying Strings` ).
output->display( `8) Transforming to Lower and Upper Case` ).
DATA(str_h1) = `It's a string`.
DATA(str_h2) = str_h1.
"The string functions store the result in a target variable.
DATA(str_h3) = to_upper( str_h1 ).
DATA(str_h4) = to_lower( str_h1 ).
"TRANSLATE does the transformation on the source variable.
TRANSLATE str_h1 TO UPPER CASE.
TRANSLATE str_h2 TO LOWER CASE.
"to_mixed/from_mixed functions
"sep: Specifies the separator
"case: A character-like text field. A small character specifies
"that the first character of the string is in lower case. If the
"specification is, for example, case = 'X', the first character
"is capitalized.
"min: A positive number that specifies the minimum number of
"characters that must appear before the separator. The default
"value is 1.
DATA(str_h5) = `A_GREAT_STRING`.
DATA(str_h6) = to_mixed( val = str_h5 sep = `_` ).
DATA(str_h7) = to_mixed( val = str_h5 sep = `_` case = 'x' ).
DATA(str_h8) = to_mixed( val = str_h5 sep = `_`
case = 'a' min = 3 ).
DATA(str_h9) = from_mixed( val = `someGreatString` sep = ` `
case = 'a' min = 4 ).
output->display( input = str_h3 name = `str_h3` ).
output->display( input = str_h4 name = `str_h4` ).
output->display( input = str_h1 name = `str_h1` ).
output->display( input = str_h2 name = `str_h2` ).
output->display( input = str_h6 name = `str_h6` ).
output->display( input = str_h7 name = `str_h7` ).
output->display( input = str_h8 name = `str_h8` ).
output->display( input = str_h9 name = `str_h9` ).
**********************************************************************
output->next_section( `9) Shifting Content in Strings` ).
DATA(str_i1) = `hallo`.
DATA(str_i2) = str_i1.
DATA(str_i3) = str_i1.
DATA(str_i4) = str_i1.
"No addition; string is shifted one place to the left
SHIFT str_i2.
"Shifting string by n places; without direction,
"left by default
SHIFT str_i3 BY 2 PLACES.
"Direction explicitly specified
"Variable-length strings are extended
SHIFT str_i4 BY 3 PLACES RIGHT.
DATA(char_i1) = 'world '.
DATA(char_i2) = char_i1.
DATA(char_i3) = char_i1.
DATA(str_i5) = `world `.
"Comparison of behavior for fixed- and variable-length strings
SHIFT char_i1 BY 3 PLACES RIGHT.
SHIFT str_i5 BY 3 PLACES RIGHT.
"CIRCULAR addition: characters that are moved out of the string are
"added at the other end again
SHIFT char_i2 BY 3 PLACES RIGHT CIRCULAR.
SHIFT char_i3 BY 2 PLACES LEFT CIRCULAR.
DATA(str_i6) = ` hallo world `.
DATA(str_i7) = str_i6.
"Moving characters up to a specific character set
SHIFT str_i6 UP TO 'or'.
"Deleting leading and trailing characters with this sequence
"of statements
SHIFT str_i7 RIGHT DELETING TRAILING ` `.
SHIFT str_i7 LEFT DELETING LEADING ` `.
"String functions storing the result in a target variable
DATA(str_i8) = `some string`.
"shift_left
DATA(str_i9) = shift_left( val = str_i8 places = 3 ).
DATA(str_i10) = shift_left( val = str_i8 circular = 7 ).
"shift_right
"Note: When the parameter places is specified, the function
"shift_right has a different behavior than the SHIFT statement.
"Here, the length of the string is reduced. SHIFT extends the
"length or it remains the same.
DATA(str_i11) = shift_right( val = str_i8 places = 3 ).
DATA(str_i12) = `shift_right and trailing blanks `.
"sub: Specifying a substring; all substrings in the string that
"match the value are removed (sub also available for shift_left)
DATA(str_i13) = shift_right( val = str_i12
sub = ` and trailing blanks ` ).
DATA(str_i14) = shift_right( val = str_i12 sub = ` ` ).
DATA(str_i15) = shift_right( val = str_i12 ). "Same effect as above
output->display( `SHIFT statements:` ).
output->display( input = str_i2 name = `str_i2` ).
output->display( input = str_i3 name = `str_i3` ).
output->display( input = str_i4 name = `str_i4` ).
output->display( input = char_i1 name = `char_i1` ).
output->display( input = str_i5 name = `str_i5` ).
output->display( input = char_i2 name = `char_i2` ).
output->display( input = char_i3 name = `char_i3` ).
output->display( input = str_i6 name = `str_i6` ).
output->display( input = str_i7 name = `str_i7` ).
output->display( `String functions:` ).
output->display( input = str_i9 name = `str_i9` ).
output->display( input = str_i10 name = `str_i10` ).
output->display( input = str_i11 name = `str_i11` ).
output->display( input = str_i13 name = `str_i13` ).
output->display( input = str_i14 name = `str_i14` ).
output->display( input = str_i15 name = `str_i15` ).
**********************************************************************
output->next_section( `10) Condensing Strings` ).
DATA(char_j1) = ' some text '.
DATA(char_j2) = ' some more text '.
DATA(char_j3) = ' a third text field literal '.
"No addition: Removes leading and trailing blanks. This is also
"true for multiple blanks. It also replaces sequences of multiple
"blanks with a single blank.
CONDENSE char_j1.
CONDENSE char_j2.
"NO-GAPS: Removes all blanks, also between words. When NO-GAPS
"is used with variable-length strings, trailing blanks remain
"removed.
CONDENSE char_j3 NO-GAPS.
"RESPECTING BLANKS: Avoiding condensing
"A use case might be the assignment of strings with fixed- to
"variable-length strings.
DATA(char_j4) = ' abcef '.
DATA(char_j5) = ' ghij '.
DATA str_j TYPE string.
"Result: ' abcef ghij '
CONCATENATE char_j4 char_j5 INTO str_j RESPECTING BLANKS.
"String function condense
"The advantage of using the string functions is
"that you can also specify random characters to be removed and
"not only blanks.
DATA(str_j1) = ` hi there `.
"No parameters specified (i. e. their default values are provided);
"works like CONDENSE statements without the NO-GAPS addition
DATA(str_j2) = condense( str_j1 ).
"Parameter 'from' specified with an initial string, 'del'/'to' not
"specified: Removes leading and trailing blanks. The 'from'
"parameter could also be specified with a text field literal:
"from = ' '
DATA(str_j3) = condense( val = str_j1 from = `` ).
"Parameter 'to' specified with an initial string, 'from'/'del' not
"specified: works like CONDENSE statements with the NO-GAPS
"addition
DATA(str_j4) = condense( val = str_j1 to = `` ).
DATA(str_j5) = `ZZseeZZZyouZZ`.
DATA(str_j6) = condense( val = str_j5 del = `Z` ).
"Parameters 'from', 'to' and 'del' are specified: Leading and
"trailing characters specified in 'del' are first removed. Then,
"in the remaining string, all substrings composed of characters
"specified in 'from' are replaced with the first character of the
"string specified in the 'to' parameter (in the example, it is a
"blank; the characters 'a', 'b', 'c' are not respected at all).
DATA(str_j7) = condense( val = str_j5
del = `Z`
from = `Z`
to = ` abc` ).
output->display( `CONDENSE statements:` ).
output->display( input = char_j1 name = `char_j1` ).
output->display( input = char_j2 name = `char_j2` ).
output->display( input = char_j3 name = `char_j3` ).
output->display( input = str_j name = `str_j` ).
output->next_section( `String function condense:` ).
output->display( input = str_j2 name = `str_j2` ).
output->display( input = str_j3 name = `str_j3` ).
output->display( input = str_j4 name = `str_j4` ).
output->display( input = str_j6 name = `str_j6` ).
output->display( input = str_j7 name = `str_j7` ).
**********************************************************************
output->next_section( `11) Reversing Strings` ).
DATA(str_k) = reverse( `ollah` ).
output->display( input = str_k name = `str_k` ).
**********************************************************************
output->next_section( `12) Inserting Substrings into Strings` ).
DATA(str_l1) = `abcghi`.
"Inserting into specific position
DATA(str_l2) = insert( val = str_l1 sub = `def` off = 3 ).
"off is optional. If not specified (default value off = 0)
"the result is like concatenating a string with &&
DATA(str_l3) = insert( val = str_l1 sub = `def` ).
DATA(str_l4) = `def` && str_l1.
output->display( input = str_l2 name = `str_l2` ).
output->display( input = str_l3 name = `str_l3` ).
output->display( input = str_l4 name = `str_l4` ).
**********************************************************************
output->next_section( `13) Overlaying Content` ).
DATA(incl) = '==============================CP'.
DATA(cl_name) = 'CL_SOME_CLASS '.
"Addition ONLY is not specified: All blanks are replaced
OVERLAY cl_name WITH incl.
DATA(t1) = 'a.b.c.a.b.c.A'.
DATA(t2) = 'z.x.y.Z.x.y.z'.
"Addition ONLY is specified: All characters that are specified after ONLY and that
"occur in the operand are replaced. Note that this is case-sensitive.
OVERLAY t1 WITH t2 ONLY 'ab'.
output->display( input = cl_name name = `cl_name` ).
output->display( input = t1 name = `t1` ).
**********************************************************************
output->next_section( `14) Processing Substrings` ).
DATA(str_m1) = `Lorem ipsum dolor sit amet`.
"Extracting substring starting at a specific position
"'len' not specified means the rest of the remaining characters are
"respected
DATA(str_m2) = substring( val = str_m1 off = 6 ).
"Extracting substring with a specific length
"'off' is not specified and has the default value 0.
DATA(str_m3) = substring( val = str_m1 len = 5 ).
"Specifying both off and len parameters
DATA(str_m4) = substring( val = str_m1 off = 6 len = 5 ).
"Excursion: Getting last character of a string
DATA(str_m5) = substring( val = str_m1
off = strlen( str_m1 ) - 1
len = 1 ). "t
"Offset and length specification using the + sign after a variable
"After +, it is the offset, length is specified within parentheses.
DATA(str_m6) = str_m1+0(5).
"* means respecting the rest of the remaining string
DATA(str_m7) = str_m1+12(*).
"Excursion: Write access on substrings in fixed-length strings
DATA(char_m1) = 'Lorem ipsum dolor sit amet'.
DATA(char_m2) = char_m1.
DATA(char_m3) = char_m1.
"Deleting content
CLEAR char_m2+11(*).
"Modifying string
char_m3+0(5) = 'abcde'.
"More string functions to access substrings
"Note that lots of parameters are possible (not all covered here).
DATA(str_m8) = `aa1bb2aa3bb4`.
"Extracting a substring ...
"... after a specified substring
DATA(str_m9) = substring_after( val = str_m8 sub = `aa` ).
"... after a specified substring specifying the occurence in a
"string and restricting the length
DATA(str_m10) = substring_after( val = str_m8 sub = `aa`
occ = 2 len = 4 ).
"... before a specified substring
DATA(str_m11) = substring_before( val = str_m8 sub = `b2` ).
"... from a specified substring on. It includes the substring
"specified in sub. len/off and other parameters are possible.
DATA(str_m12) = substring_from( val = str_m8 sub = `a3` ).
"... up to a specified substring. It includes the substring
"specified in sub. len/off and other parameters are possible.
"aa1bb2aa3b
DATA(str_m13) = substring_to( val = str_m8 sub = `3b` ).
output->display( input = str_m2 name = `str_m2` ).
output->display( input = str_m3 name = `str_m3` ).
output->display( input = str_m4 name = `str_m4` ).
output->display( input = str_m5 name = `str_m5` ).
output->display( input = str_m6 name = `str_m6` ).
output->display( input = str_m7 name = `str_m7` ).
output->display( input = char_m2 name = `char_m2` ).
output->display( input = char_m3 name = `char_m3` ).
output->display( input = str_m9 name = `str_m9` ).
output->display( input = str_m10 name = `str_m10` ).
output->display( input = str_m11 name = `str_m11` ).
output->display( input = str_m12 name = `str_m12` ).
output->display( input = str_m13 name = `str_m13` ).
**********************************************************************
output->next_section( `Searching and Replacing in Strings` ).
output->display( `15) Searching Specific Characters in Strings ` &&
`Using Comparison Operators and String Functions` ).
DATA(str_n1) = `cheers`.
"CA (contains any)
"sy-fdpos contains the offset of the first found character.
"If nothing is found, sy-fdpos contains the length of the string.
"Note that position 0 stands for the very first position.
IF str_n1 CA `aeiou`.
output->display( |CA: str_n1 contains any of the characters. | &&
|The position of the first found character is { sy-fdpos }.| ).
ELSE.
output->display( |CA: str_n1 does not contain any of the characters. | &&
|The length of str_n1 is { sy-fdpos }.| ).
ENDIF.
"NA (contains not any)
IF str_n1 NA `xyz`.
output->display( |NA: str_n1 does not contain any of the characters.| &&
|The length of str_n1 is { sy-fdpos }.|
).
ELSE.
output->display( |NA: str_n1 contains any of the characters. | &&
|The position of the first found character is { sy-fdpos }.| ).
ENDIF.
"Determining if a string is exclusively composed of a certain
"character set
IF str_n1 CO `rs`.
output->display( |CO: str_n1 contains only the characters. |
&& |The length of str_n1 is { sy-fdpos }.| ).
ELSE.
output->display( |CO: str_n1 does not contain only the characters. |
&& |Offset of the first character in str_n1 that is not |
&& |contained in the second operand: { sy-fdpos }.| ).
ENDIF.
"Negation of CO
IF str_n1 CN `chers`.
output->display( |CN: str_n1 does not contain only the characters. |
&& |Offset of the first character in str_n1 that is |
&& |not contained in the second operand: { sy-fdpos }.|
).
ELSE.
output->display( |CN: str_n1 contains only the characters. |
&& |The length of str_n1 is { sy-fdpos }.| ).
ENDIF.
"String functions
DATA(str_n2) = `Pieces of cakes.`.
"find_end returns the sum of the offset of the occurrence
DATA(res_n3) = find_end( val = str_n2 sub = `of` ). "9
"find_any_of returns the offset of the occurrence of any character contained in substring
"The search is always case-sensitive.
DATA(res_n4) = find_any_of( val = str_n2 sub = `x523z4e` ).
DATA(res_n5) = find_any_of( val = str_n2 sub = `zwq85t` ).
"find_any_not_of: Negation of the one above
"The search is always case-sensitive.
DATA(res_n6) = find_any_not_of( val = str_n2 sub = `ieces` ).
DATA(res_n7) = find_any_not_of( val = str_n2 sub = `P` ).
"count returns the number of all occurrences
DATA(res_n8) = count( val = str_n2 sub = `e` ).
DATA(res_n9) = count( val = str_n2 sub = `x` ).
"count_any_of
DATA(res_n10) = count_any_of( val = str_n2 sub = `x523z4e` ).
DATA(res_n11) = count_any_of( val = str_n2 sub = `eco` ).
"count_any_not_of
DATA(res_n12) = count_any_not_of( val = str_n2 sub = `fP` ).
DATA(res_n13) = count_any_not_of( val = str_n2 sub = `Piecs ofak.` ).
output->display( input = res_n3 name = `res_n3` ).
output->display( input = res_n4 name = `res_n4` ).
output->display( input = res_n5 name = `res_n5` ).
output->display( input = res_n6 name = `res_n6` ).
output->display( input = res_n7 name = `res_n7` ).
output->display( input = res_n8 name = `res_n8` ).
output->display( input = res_n9 name = `res_n9` ).
output->display( input = res_n10 name = `res_n10` ).
output->display( input = res_n11 name = `res_n11` ).
output->display( input = res_n12 name = `res_n12` ).
output->display( input = res_n13 name = `res_n13` ).
**********************************************************************
output->next_section( `16) Replacing Specific Characters in Strings` ).
DATA(str_o1) = `___abc_def_____ghi_`.
"The replacement is done as follows: Each character specified in
"'from' is replaced by the character in 'to' that is on the same
"position, i. e. the second character in 'from' is replaced by the
"second character specified in 'to'. If there is no equivalent in
"'to', the character in 'from' is removed from the result.
"abcdefgZZ
DATA(str_o2) = translate( val = str_o1 from = `hi_` to = `ZZ` ).
"ZZZabcZdefZZZZZghiZ
DATA(str_o3) = translate( val = str_o1 from = `_` to = `ZZ` ).
"TRANSLATE statement. The value after USING is interpreted as a
"string composed of character pairs. Starting with the first pair,
"a search is performed in text for the first character in every
"pair and each occurrence is replaced with the second character of
"the pair.
"...Zbc.def.....Yhi.
TRANSLATE str_o1 USING `_.aZgY`.
output->display( input = str_o2 name = `str_o2` ).
output->display( input = str_o3 name = `str_o3` ).
output->display( input = str_o1 name = `str_o1` ).
**********************************************************************
output->next_section( `Searching for Substrings in Strings` ).
output->display( `17) Substring Search: Simple Search Using Comparison Operators` ).
DATA(str_p1) = `cheers`.
"CS (contains string)
"sy-fdpos contains the offset of the found substring.
"If the substring is not found, sy-fdpos contains the length of the
"searched string.
IF str_p1 CS `rs`.
output->display( |CS: The string contains the substring. |
&& |The offset is { sy-fdpos }.| ).
ELSE.
output->display( |CS: The string does not contain the substring. |
&& |The length of the string is { sy-fdpos }.| ).
ENDIF.
"NS (contains no string)
IF str_p1 NS `abc`.
output->display( |NS: The string does not contain the substring. |
&& |The length of the string is { sy-fdpos }.| ).
ELSE.
output->display( |NS: The string contains the substring. |
&& |The offset is { sy-fdpos }.| ).
ENDIF.
**********************************************************************
output->next_section( `18) Substring Search in Strings ` &&
`Using FIND Statements` ).
"The code examples demonstrate different additions.
DATA(str_qa) = `She sells seashells by the seashore.`.
"Determining if a substring is found
"Simple find statement
FIND `se` IN str_qa.
IF sy-subrc = 0.
output->display( `'se' found in the string` ).
ELSE.
output->display( `'se' not found in the string` ).
ENDIF.
"Addition SUBSTRING is optional
FIND SUBSTRING `hi` IN str_qa.
IF sy-subrc = 0.
output->display( `'hi' Found in the string` ).
ELSE.
output->display( `'hi' not found in the string` ).
ENDIF.
"The following examples use the additions MATCH COUNT and MATCH OFFSET
"to determine the number of occurrences and offset and for display purposes.
"Addition FIRST OCCURRENCE OF: Explicit specification to search
"for the first occurrence
FIND FIRST OCCURRENCE OF `se` IN str_qa
MATCH COUNT DATA(cnt_q1)
MATCH OFFSET DATA(off_q2).
"Omitting FIRST OCCURRENCE OF and ALL OCCURRENCES OF addition means
"searching for the first occurrence by default; same effect as the
"previous statement
FIND `se` IN str_qa
MATCH COUNT DATA(cnt_q3)
MATCH OFFSET DATA(off_q4).
"Addition ALL OCCURRENCES: Searching for all occurrences
FIND ALL OCCURRENCES OF `se` IN str_qa
MATCH COUNT DATA(cnt_q5)
MATCH OFFSET DATA(off_q6). "value for the last occurrence
"Addition IN SECTION ... OF:
"Searching in a specified section; both additions OFFSET and LENGTH
"are specified
FIND ALL OCCURRENCES OF `se`
IN SECTION OFFSET 9 LENGTH 5 OF str_qa
MATCH COUNT DATA(cnt_q7)
MATCH OFFSET DATA(off_q8).
"Only LENGTH specified (OFFSET is 0 by default)
FIND ALL OCCURRENCES OF `se`
IN SECTION LENGTH 7 OF str_qa
MATCH COUNT DATA(cnt_q9)
MATCH OFFSET DATA(off_q10).
"Only OFFSET specified (LENGTH: up to end of string)
FIND ALL OCCURRENCES OF `se`
IN SECTION OFFSET 7 OF str_qa
MATCH COUNT DATA(cnt_q11).
"Another string to be searched
DATA(str_qb) = `abap ABAP abap`.
"Further additional options for advanced evaluation options
"Specifying the case-sensitivity of the search
"Not specifying the CASE addition means RESPECTING CASE is used by default.
"Here, it is explicitly specified.
FIND FIRST OCCURRENCE OF `A` IN str_qb
MATCH OFFSET DATA(off_q12)
RESPECTING CASE.
"Making search case-insensitive
FIND FIRST OCCURRENCE OF `A` IN str_qb
MATCH OFFSET DATA(off_q13)
IGNORING CASE.
"MATCH LENGTH addition
"The example uses a regular expression: Non-greedy search for
"a substring starting with lower case a up to an upper case P
FIND FIRST OCCURRENCE OF PCRE `a.*?P` IN str_qb
MATCH LENGTH DATA(len_q14) "9
RESPECTING CASE.
"RESULTS addition
"Example: Because of using ALL OCCURRENCES, the data object declared
"inline automatically has the type match_result_tab
FIND ALL OCCURRENCES OF `ab` IN str_qb
RESULTS DATA(res_q15)
IGNORING CASE.
"Because of searching for the first occurrence, the data object declared
"inline automatically has the type match_result
FIND FIRST OCCURRENCE OF `ab` IN str_qb
RESULTS DATA(res_q16)
IGNORING CASE.
output->display( input = cnt_q1 name = `cnt_q1` ).
output->display( input = off_q2 name = `off_q2` ).
output->display( input = cnt_q3 name = `cnt_q3` ).
output->display( input = off_q4 name = `off_q4` ).
output->display( input = cnt_q5 name = `cnt_q5` ).
output->display( input = off_q6 name = `off_q6` ).
output->display( input = cnt_q7 name = `cnt_q7` ).
output->display( input = off_q8 name = `off_q8` ).
output->display( input = cnt_q9 name = `cnt_q9` ).
output->display( input = off_q10 name = `off_q10` ).
output->display( input = cnt_q11 name = `cnt_q11` ).
output->display( input = off_q12 name = `off_q12` ).
output->display( input = off_q13 name = `off_q13` ).
output->display( input = len_q14 name = `len_q14` ).
output->display( input = res_q15 name = `res_q15` ).
output->display( input = res_q16 name = `res_q16` ).
**********************************************************************
output->next_section( `19) Substring Search in Internal Tables ` &&
`Using FIND ... IN TABLE Statements` ).