STRING and UNSTRING

COBOL COBOL 2014 (ISO/IEC 1989:2014), built with GnuCOBOL 3.x Β· βœ“ verified by execution on 2026-08-16

COBOL provides specialized verbs for manipulating text data: STRING for concatenation and UNSTRING for splitting strings. While MOVE is great for simple assignments, it lacks the flexibility to combine multiple fields or parse delimited data like CSVs or log files. This is where STRING and UNSTRING become invaluable tools in your COBOL toolkit.

Concatenating Data with STRING

The STRING statement allows you to combine the contents of two or more data items into a single receiving field. You can concatenate entire fields or just parts of them.

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. StringBasic.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  FIRST-NAME PIC X(5) VALUE "JOHN ".
       01  LAST-NAME  PIC X(5) VALUE "SMITH".
       01  FULL-NAME  PIC X(11) VALUE SPACES.
       PROCEDURE DIVISION.
           STRING FIRST-NAME DELIMITED BY SIZE
                  " " DELIMITED BY SIZE
                  LAST-NAME DELIMITED BY SIZE
                  INTO FULL-NAME.
           DISPLAY "[" FULL-NAME "]".
           STOP RUN.
Output
[JOHN  SMITH]

A crucial detail about STRING is how it handles memory in the receiving field. Unlike a MOVE statement which often pads the rest of the field with spaces (if it’s alphanumeric), STRING only modifies the exact bytes it writes. The rest of the receiving field remains untouched.

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. StringPad.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  FIRST-NAME PIC X(5) VALUE "JOHN ".
       01  FULL-NAME  PIC X(10) VALUE "XXXXXXXXXX".
       PROCEDURE DIVISION.
           STRING FIRST-NAME DELIMITED BY SPACE
                  INTO FULL-NAME.
           DISPLAY FULL-NAME.
           STOP RUN.
Output
JOHNXXXXXX

Notice how XXXXXX remains at the end? If you need a clean string, you must initialize the receiving field with SPACES before executing the STRING statement.

The Memory Layout

Memory Layout of STRING JOHN SMITH JOHN SMITH

Parsing Data with UNSTRING

The UNSTRING statement does the opposite: it takes a single sending field and breaks it apart based on delimiters, placing the pieces into multiple receiving fields. This is perfect for processing CSV files or other structured text formats.

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. UnstringBasic.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  CSV-DATA PIC X(20) VALUE "JANE,DOE,30".
       01  F-NAME   PIC X(10).
       01  L-NAME   PIC X(10).
       01  AGE      PIC X(2).
       PROCEDURE DIVISION.
           UNSTRING CSV-DATA DELIMITED BY ","
             INTO F-NAME L-NAME AGE.
           DISPLAY "FIRST: " F-NAME.
           DISPLAY "LAST:  " L-NAME.
           DISPLAY "AGE:   " AGE.
           STOP RUN.
Output
FIRST: JANE      
LAST:  DOE       
AGE:   30

The ALL Keyword in UNSTRING

One of the most common pitfalls with UNSTRING is dealing with consecutive delimiters. For example, if you are parsing a string delimited by spaces, what happens if there are two spaces in a row? Without the ALL keyword, UNSTRING treats the empty space between the two delimiters as a valid, empty field!

Predict the output cobol

Read the code. What exactly will it print? Commit to an answer before you look.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. PredictUnstring.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  DATA-STR PIC X(20) VALUE "A  B".
       01  F1 PIC X(2).
       01  F2 PIC X(2).
       PROCEDURE DIVISION.
           UNSTRING DATA-STR DELIMITED BY SPACE
             INTO F1 F2.
           DISPLAY "[" F1 "] [" F2 "]".
           STOP RUN.
Output
[A ] [  ]

To avoid this and treat multiple consecutive spaces (or any delimiter) as a single separator, you must use the ALL keyword.

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. UnstringAll.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  SPACED-DATA PIC X(20) VALUE "WORD1   WORD2  WORD3".
       01  W1 PIC X(5).
       01  W2 PIC X(5).
       01  W3 PIC X(5).
       PROCEDURE DIVISION.
           UNSTRING SPACED-DATA DELIMITED BY ALL SPACE
             INTO W1 W2 W3.
           DISPLAY W1 "|" W2 "|" W3.
           STOP RUN.
Output
WORD1|WORD2|WORD3

Advanced Parsing with Pointers and Tallying

For even more control, you can use WITH POINTER to resume string operations from a specific offset, and TALLYING IN to count exactly how many receiving fields were filled by an UNSTRING operation.

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. UnstringCount.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  CSV PIC X(15) VALUE "A,B,C,D".
       01  OUT1 PIC X.
       01  OUT2 PIC X.
       01  OUT3 PIC X.
       01  NUM-FIELDS PIC 9 VALUE 0.
       PROCEDURE DIVISION.
           UNSTRING CSV DELIMITED BY ","
             INTO OUT1 OUT2 OUT3
             TALLYING IN NUM-FIELDS.
           DISPLAY "FILLED: " NUM-FIELDS.
           STOP RUN.
Output
FILLED: 3

These advanced clauses provide the foundation for writing robust string parsers entirely in COBOL, avoiding the need for complex, manual character-by-character loops. This is a very common requirement when dealing with mainframe data files or interacting with other systems that output delimited data formats. Mastering string handling is a significant step toward writing complete COBOL applications.

Check yourself

If you STRING two fields together, what happens to the remaining characters in the receiving field if it is larger than the combined data?

Reveal answer

The remaining characters are left unchanged. β€” STRING only overwrites the characters it explicitly places. Unoverwritten characters remain in the receiving field.

What happens if you use UNSTRING with 'DELIMITED BY SPACE' on a string containing consecutive spaces?

Reveal answer

It creates empty intermediate fields for each extra space. β€” Without the ALL keyword, consecutive spaces result in empty intermediate fields being processed.

What happens if there are more parts in the source string than receiving fields in the UNSTRING statement?

Reveal answer

The extra parts are ignored unless ON OVERFLOW is specified. β€” If there are too few fields, the remainder is ignored. ON OVERFLOW can be used to handle this condition.

Challenges

Challenge 1 +20 XP

Use the STRING statement to combine FIRST-NAME and LAST-NAME with a space in between into FULL-NAME. Stop copying when you encounter a space in the source fields.

cobol βœ“ solution verified at build time

COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the fixed code should be, then open the solution and compare. The expected output below is real β€” it came from compiling the solution with GnuCOBOL when this page was built.

  • Test 1 β€” expects "[ADA LOVELACE ]"
Need a hint? (βˆ’25% XP)

Use DELIMITED BY SPACE for the names and DELIMITED BY SIZE for the literal space.

Show solution (0 XP)
       IDENTIFICATION DIVISION.
       PROGRAM-ID. Chal1Sol.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  FIRST-NAME PIC X(10) VALUE "ADA       ".
       01  LAST-NAME  PIC X(10) VALUE "LOVELACE  ".
       01  FULL-NAME  PIC X(20) VALUE SPACES.
       PROCEDURE DIVISION.
           STRING FIRST-NAME DELIMITED BY SPACE
                  " " DELIMITED BY SIZE
                  LAST-NAME DELIMITED BY SPACE
                  INTO FULL-NAME.
           DISPLAY "[" FULL-NAME "]"
           STOP RUN.

🐞 Bug Hunt +20 XP

This UNSTRING statement is failing to parse the log entry correctly because it's missing the ALL keyword for spaces. Fix the bug!

This code runs. It just does the wrong thing. Read it, find the defect, fix it β€” the tests below decide when you are right.

cobol βœ“ solution verified at build time

COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the fixed code should be, then open the solution and compare. The expected output below is real β€” it came from compiling the solution with GnuCOBOL when this page was built.

  • Test 1 β€” expects "10.0.0.1 \nadmin \nLogin-failed "
Need a hint? (βˆ’25% XP)

Use DELIMITED BY ALL SPACE to handle consecutive spaces.

Show solution (0 XP)
       IDENTIFICATION DIVISION.
       PROGRAM-ID. Chal2Sol.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  LOG-ENTRY  PIC X(30) VALUE "10.0.0.1  admin  Login-failed".
       01  IP-ADDRESS PIC X(15) VALUE SPACES.
       01  USER-ID    PIC X(10) VALUE SPACES.
       01  MSG        PIC X(15) VALUE SPACES.
       PROCEDURE DIVISION.
           UNSTRING LOG-ENTRY DELIMITED BY ALL SPACE
             INTO IP-ADDRESS USER-ID MSG.
           DISPLAY IP-ADDRESS
           DISPLAY USER-ID
           DISPLAY MSG
           STOP RUN.