ABAP Dojo › Guides › String Processing

ABAP String Processing: CONCATENATE, && and STRLEN

String handling in ABAP has evolved significantly over the years. Understanding the difference between STRING and CHAR(n) types, and knowing both legacy and modern syntax, is essential for writing correct and maintainable ABAP code. This guide covers the most common string operations with runnable examples.

The short answer

String Types in ABAP

ABAP has two fundamentally different string types: STRING is a dynamic-length heap-allocated string, while CHAR(n) is a fixed-length character field stored inline. Using STRING where CHAR(n) is expected (e.g. a database field) causes implicit conversions and potential truncation bugs. Choose the type that matches your use case and the target field definition.

" Fixed-length: padded with blanks to the declared length
DATA lv_char TYPE c LENGTH 20.      " or: CHAR20 / char20
lv_char = 'Hello'.                  " stored as 'Hello               '

" Dynamic-length: no padding, heap-allocated
DATA lv_string TYPE string.
lv_string = 'Hello'.                " stored as 'Hello' (5 chars)

Concatenation with && and String Templates

Since ABAP 7.02, you can use the && operator to concatenate strings inline, much like + in Python or Java. This is more readable than the legacy CONCATENATE statement and works naturally in assignments and expressions. String templates with |...| syntax are often clearer still, because the blanks you type between the braces are exactly the blanks you get.

DATA: lv_first  TYPE string VALUE 'John',
      lv_last   TYPE string VALUE 'Doe',
      lv_result TYPE string.

" Using && with a `string literal` (backquotes keep the blank)
lv_result = lv_first && ` ` && lv_last.
WRITE: / lv_result.  " John Doe

" Using a string template (usually the clearest)
lv_result = |{ lv_first } { lv_last }|.
WRITE: / lv_result.  " John Doe

Note the backquotes around the blank. The version almost everyone writes first, lv_first && ' ' && lv_last, prints JohnDoe.

Why the Space Disappears: ' ' vs ` `

ABAP has two kinds of literal. '...' is a text field literal: it has the fixed-length type c, and trailing blanks in a c value are treated as padding, not content. So when it is used in a string expression or as a CONCATENATE operand, ' ' contributes nothing at all. `...` is a string literal of type string, and every character in it, blanks included, is kept.

The separator of CONCATENATE ... SEPARATED BY is the exception: its blanks are kept, which is why SEPARATED BY space works.

REPORT zspace_gotcha.

DATA: lv_first  TYPE string VALUE 'John',
      lv_last   TYPE string VALUE 'Doe',
      lv_result TYPE string.

" 'text field literal': the trailing blank is dropped
lv_result = lv_first && ' ' && lv_last.
WRITE: / lv_result.  " JohnDoe

" `string literal`: the blank is kept
lv_result = lv_first && ` ` && lv_last.
WRITE: / lv_result.  " John Doe

" CONCATENATE drops it from an operand too...
CONCATENATE lv_first ' ' lv_last INTO lv_result.
WRITE: / lv_result.  " JohnDoe

" ...but not from the separator
CONCATENATE lv_first lv_last INTO lv_result SEPARATED BY space.
WRITE: / lv_result.  " John Doe

This is also one of the most common mistakes in AI-generated ABAP: models write ' ' because that is how a space is written in most other languages.

Run this comparison in ABAP Dojo →

CONCATENATE Statement

The CONCATENATE statement joins multiple strings into a target variable and optionally inserts a separator with SEPARATED BY. You will encounter this pattern frequently in existing ABAP codebases, so knowing how to read it is important. For new code, prefer the && operator or string templates instead.

DATA: lv_city    TYPE string VALUE 'Tokyo',
      lv_country TYPE string VALUE 'Japan',
      lv_result  TYPE string.

" Plain CONCATENATE: operands are joined with nothing in between
CONCATENATE lv_city lv_country INTO lv_result.
WRITE: / lv_result.  " TokyoJapan

" SEPARATED BY: the separator keeps its blanks
CONCATENATE lv_city lv_country INTO lv_result SEPARATED BY ', '.
WRITE: / lv_result.  " Tokyo, Japan

" SEPARATED BY space: the classic way to insert one blank
CONCATENATE lv_city lv_country INTO lv_result SEPARATED BY space.
WRITE: / lv_result.  " Tokyo Japan

Try CONCATENATE in ABAP Dojo →

RESPECTING BLANKS

Operands of fixed-length types (c, n, d, t) lose their trailing blanks when concatenated. Add RESPECTING BLANKS when the padding matters, for example when building fixed-width file records.

DATA: lv_code   TYPE c LENGTH 6 VALUE 'AB',
      lv_result TYPE string.

" Fixed-length fields lose their padding by default
CONCATENATE lv_code 'X' INTO lv_result.
WRITE: / lv_result.  " ABX

" RESPECTING BLANKS keeps the full field length
CONCATENATE lv_code 'X' INTO lv_result RESPECTING BLANKS.
WRITE: / lv_result.  " AB    X

CONCATENATE LINES OF an Internal Table

To join every line of an internal table, use CONCATENATE LINES OF, or the concat_lines_of( ) function when you want an expression. Without sep, concat_lines_of( ) joins the lines with nothing in between.

DATA: lt_parts  TYPE STANDARD TABLE OF string WITH EMPTY KEY,
      lv_result TYPE string.

APPEND `red` TO lt_parts.
APPEND `green` TO lt_parts.
APPEND `blue` TO lt_parts.

" Statement form
CONCATENATE LINES OF lt_parts INTO lv_result SEPARATED BY `, `.
WRITE: / lv_result.  " red, green, blue

" Expression form (ABAP 7.02+)
lv_result = concat_lines_of( table = lt_parts sep = `, ` ).
WRITE: / lv_result.  " red, green, blue

String Length with STRLEN( )

strlen( ) returns the number of characters in a string. It is the standard function for getting string length in ABAP and works on both STRING and CHAR(n) types. ABAP keywords and built-in functions are not case-sensitive, so STRLEN( ) and strlen( ) are the same call. Note the blanks inside the parentheses: strlen(lv_text) without them is a syntax error.

DATA: lv_text   TYPE string VALUE 'Hello, ABAP!',
      lv_length TYPE i.

lv_length = strlen( lv_text ).
WRITE: / 'Length:', lv_length.  " Length: 12

" Useful for conditional checks
IF strlen( lv_text ) > 10.
  WRITE: / 'String is longer than 10 characters.'.
ENDIF.

STRLEN and trailing blanks

What strlen( ) counts depends on the type. For a CHAR field, the padding is not counted, so a c LENGTH 10 field holding 'Hi' has length 2, not 10. For a STRING, trailing blanks count, but only if they made it into the string in the first place.

DATA: lv_char   TYPE c LENGTH 10 VALUE 'Hi',
      lv_string TYPE string,
      lv_length TYPE i.

" CHAR field: trailing padding is not counted
lv_length = strlen( lv_char ).
WRITE: / 'CHAR(10):', lv_length.  " CHAR(10): 2

" STRING from a `string literal`: trailing blanks count
lv_string = `Hi  `.
lv_length = strlen( lv_string ).
WRITE: / 'string:', lv_length.  " string: 4

" STRING from a 'text field literal': the blanks were dropped on assignment
lv_string = 'Hi  '.
lv_length = strlen( lv_string ).
WRITE: / 'from literal:', lv_length.  " from literal: 2

Try STRLEN in ABAP Dojo →

Case Conversion with TRANSLATE

The TRANSLATE statement converts a string to upper or lower case in place. It modifies the variable directly rather than returning a new value, which is a common gotcha for developers coming from other languages. For read-only conversions without side effects, use the to_upper / to_lower string functions.

DATA lv_text TYPE string VALUE 'Hello World'.

" TRANSLATE modifies the variable in place
TRANSLATE lv_text TO UPPER CASE.
WRITE: / lv_text.  " HELLO WORLD

TRANSLATE lv_text TO LOWER CASE.
WRITE: / lv_text.  " hello world

" Expression-style alternative, no side effects
DATA lv_upper TYPE string.
lv_upper = to_upper( lv_text ).
WRITE: / lv_upper.  " HELLO WORLD
WRITE: / lv_text.   " hello world (unchanged)

Full Example

This example combines the core operations from this guide: &&, string templates, strlen( ), to_upper( ) and CONCATENATE. Open it in ABAP Dojo and click Run to see each technique in action.

REPORT zstring_processing.

DATA: lv_first    TYPE string VALUE 'John',
      lv_last     TYPE string VALUE 'Doe',
      lv_full     TYPE string,
      lv_quoted   TYPE string,
      lv_length   TYPE i,
      lv_upper    TYPE string,
      lv_city     TYPE string VALUE 'Berlin',
      lv_country  TYPE string VALUE 'Germany',
      lv_location TYPE string.

" Concatenation with && (backquotes keep the blank)
lv_full = lv_first && ` ` && lv_last.
WRITE: / 'Full name:', lv_full.

" The same with ' ' loses the blank
lv_quoted = lv_first && ' ' && lv_last.
WRITE: / 'With quotes:', lv_quoted.

" String template
WRITE: / |Hello, { lv_full }!|.

" Length
lv_length = strlen( lv_full ).
WRITE: / 'Name length:', lv_length.

" Upper case
lv_upper = to_upper( lv_full ).
WRITE: / 'Upper case:', lv_upper.

" Legacy CONCATENATE with SEPARATED BY
CONCATENATE lv_city lv_country INTO lv_location SEPARATED BY ', '.
WRITE: / 'Location:', lv_location.
Try this code in ABAP Dojo →