COBOL COBOL 2014 (ISO/IEC 1989:2014), built with GnuCOBOL 3.x ·
✓ verified by execution on 2026-08-16
Most programming languages use functions or methods like substring() to extract a portion of a string. COBOL does it natively using a syntax called reference modification. In modern high-level languages, strings are treated as dynamic objects, and you manipulate them by calling library methods. COBOL, designed for processing massive fixed-width flat files, treats strings and alphanumeric data as strict blocks of memory. Because of this, it provides a powerful, built-in syntax to slice directly into memory without overhead.
The COBOL 1985 standard introduced the concept of a reference modifier to facilitate references to only a portion of a data item. You simply append parentheses containing a starting position and a length directly to the variable name: identifier(start:length).
The 1-Based Index
If you are coming from C, Java, Python, or JavaScript, the most important thing to learn about COBOL reference modification is that COBOL uses 1-based indexing. The start value indicates the starting character position being referenced, and character position values start with 1, not 0.
Here is a visual representation of how a COBOL string sits in memory:
To extract the first 9 characters of a string, you start at position 1 and specify a length of 9:
When writing (start:length), the second number is the length of the substring, not the ending position. This trips up nearly everyone when they first write COBOL.
Predict the outputcobol
Read the code. What exactly will it print? Commit to an answer before you look.
IDENTIFICATION DIVISION. PROGRAM-ID. LEN-VS-END. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-ALPHABET PIC X(10) VALUE 'ABCDEFGHIJ'. 01 WS-PART PIC X(5). PROCEDURE DIVISION. MOVE WS-ALPHABET(3:5) TO WS-PART. DISPLAY 'Part: ' WS-PART. STOP RUN.
Output
Part: CDEFG
You predicted
Notice that WS-ALPHABET(3:5) does not mean “from position 3 to position 5”. It means “start at position 3, and grab 5 characters”.
Extracting to the End
If you omit the length parameter completely, COBOL is smart enough to assume you want everything from your specified starting position all the way to the very end of the variable’s defined PIC length. This is particularly useful when extracting a variable-length suffix or when the exact length is cumbersome to calculate manually.
Reference modification is not just for reading parts of a string. It may be used anywhere an identifier is legal, including serving as the receiving field of statements like MOVE. You can overwrite a specific slice of a variable without touching the rest of it.
When you use reference modification on the receiving side of a MOVE statement, the rest of the variable remains completely untouched. This is incredibly useful for manipulating fixed-format records, such as updating only the month portion of a date field or replacing a specific digit in a serial number.
cobol✓ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. WRITE-SUB. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-DATE PIC X(10) VALUE '2026-01-01'. PROCEDURE DIVISION. MOVE '12' TO WS-DATE(6:2). DISPLAY 'New Date: ' WS-DATE. STOP RUN.
Output
New Date: 2026-12-01
Your output
Dynamic Reference Modification
You do not have to hardcode the start and length values. Both start and length may be specified as integer numeric literals, integer numeric data items, or arithmetic expressions with an integer value.
In real-world mainframe applications, you will often need to parse data where the positions are not known until runtime. COBOL allows you to use variables instead of hardcoded numbers. When doing this, be extremely careful: if your variables cause the start or length to exceed the variable’s boundaries, you may trigger an out-of-bounds error or silently corrupt adjacent memory, depending on the compiler.
cobol✓ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. VAR-IDX. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-TEXT PIC X(15) VALUE 'APPLE BANANA'. 01 WS-START PIC 99 VALUE 7. 01 WS-LEN PIC 99 VALUE 6. 01 WS-RESULT PIC X(10). PROCEDURE DIVISION. MOVE WS-TEXT(WS-START:WS-LEN) TO WS-RESULT. DISPLAY 'Fruit: ' WS-RESULT. STOP RUN.
Output
Fruit: BANANA
Your output
You can even combine reference modification on both the source and destination fields in the same statement:
cobol✓ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. SUB-TO-SUB. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-SOURCE PIC X(15) VALUE 'ID: 987654321'. 01 WS-DEST PIC X(15) VALUE 'USER-000000'. PROCEDURE DIVISION. MOVE WS-SOURCE(5:6) TO WS-DEST(6:6). DISPLAY 'Dest: ' WS-DEST. STOP RUN.
Output
Dest: USER-987654
Your output
Check yourself
In COBOL reference modification, what does `WS-DATA(3:5)` mean?
Reveal answer
Extract 5 characters, starting at position 3 — The first number is the starting position (1-based). The second number is the LENGTH, not the end position.
What happens if you omit the length, as in `WS-DATA(4:)`?
Reveal answer
It extracts everything from position 4 to the end of the string — If no length is specified, COBOL assumes a value equivalent to the remaining character positions from the start to the end of the item.
Are COBOL strings 0-indexed or 1-indexed?
Reveal answer
1-indexed (the first character is position 1) — COBOL uses 1-based indexing. Position 1 is the leftmost character.
Challenges
Challenge 1 +10 XP
Extract the year from WS-DATE into WS-YEAR using reference modification.
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 "Year is: 2026\n"
Need a hint? (−25% XP)
Start at character 7 for a length of 4.
Show solution (0 XP)
IDENTIFICATION DIVISION.PROGRAM-ID. EXTRACT-YEAR.DATA DIVISION.WORKING-STORAGE SECTION.01 WS-DATE PIC X(10) VALUE '15/08/2026'.01 WS-YEAR PIC X(4).PROCEDURE DIVISION. MOVE WS-DATE(7:4) TO WS-YEAR. DISPLAY 'Year is: ' WS-YEAR. STOP RUN.
🐞 Bug Hunt+15 XP
This program has a silent bug. It tries to extract the 5-character serial from the part number starting after the PX-, but it gets it wrong. Find and fix the error.
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 "Serial: 10294\n"
Need a hint? (−25% XP)
The first character is at position 1. The P is 1, X is 2, the hyphen is 3, so the serial starts at 4.