MainframeMaster

COBOL Tutorial

COBOL DELIMITED BY

The DELIMITED BY clause in COBOL is used to specify delimiter characters for string operations, enabling powerful text parsing, data extraction, and field separation capabilities.

Basic DELIMITED BY Syntax

DELIMITED BY is primarily used with UNSTRING and STRING statements to control how data is parsed or concatenated based on delimiter characters.

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
*> UNSTRING with DELIMITED BY UNSTRING source-string DELIMITED BY delimiter-character INTO receiving-field-1, receiving-field-2, ... [WITH POINTER pointer-field] [TALLYING IN count-field] [ON OVERFLOW imperative-statement] END-UNSTRING *> STRING with DELIMITED BY STRING source-field-1 DELIMITED BY delimiter-1 source-field-2 DELIMITED BY delimiter-2 INTO target-string [WITH POINTER pointer-field] [ON OVERFLOW imperative-statement] END-STRING

UNSTRING with DELIMITED BY

Basic String Parsing

cobol
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
DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-INPUT-STRING PIC X(100). 01 WS-PARSED-FIELDS. 05 WS-FIELD-1 PIC X(20). 05 WS-FIELD-2 PIC X(20). 05 WS-FIELD-3 PIC X(20). 05 WS-FIELD-4 PIC X(20). 05 WS-FIELD-5 PIC X(20). 01 WS-COUNTERS. 05 WS-FIELD-COUNT PIC 9(2). 05 WS-POINTER PIC 9(3). PROCEDURE DIVISION. BASIC-PARSING-DEMO. DISPLAY "=== Basic DELIMITED BY Parsing ===" *> Example 1: Comma-separated values MOVE "Apple,Orange,Banana,Grape,Cherry" TO WS-INPUT-STRING UNSTRING WS-INPUT-STRING DELIMITED BY "," INTO WS-FIELD-1, WS-FIELD-2, WS-FIELD-3, WS-FIELD-4, WS-FIELD-5 TALLYING IN WS-FIELD-COUNT END-UNSTRING DISPLAY "CSV Parsing Results:" DISPLAY "Field 1: '" WS-FIELD-1 "'" DISPLAY "Field 2: '" WS-FIELD-2 "'" DISPLAY "Field 3: '" WS-FIELD-3 "'" DISPLAY "Field 4: '" WS-FIELD-4 "'" DISPLAY "Field 5: '" WS-FIELD-5 "'" DISPLAY "Fields parsed: " WS-FIELD-COUNT *> Example 2: Space-separated values INITIALIZE WS-PARSED-FIELDS MOVE "John Doe 25 Engineer USA" TO WS-INPUT-STRING UNSTRING WS-INPUT-STRING DELIMITED BY SPACE INTO WS-FIELD-1, WS-FIELD-2, WS-FIELD-3, WS-FIELD-4, WS-FIELD-5 TALLYING IN WS-FIELD-COUNT END-UNSTRING DISPLAY " " DISPLAY "Space-delimited parsing:" DISPLAY "First Name: '" WS-FIELD-1 "'" DISPLAY "Last Name: '" WS-FIELD-2 "'" DISPLAY "Age: '" WS-FIELD-3 "'" DISPLAY "Occupation: '" WS-FIELD-4 "'" DISPLAY "Country: '" WS-FIELD-5 "'" DISPLAY "Fields parsed: " WS-FIELD-COUNT.

Multiple Delimiters

cobol
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
DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-COMPLEX-STRING PIC X(200). 01 WS-EXTRACTED-DATA. 05 WS-ITEM OCCURS 10 TIMES PIC X(30). 01 WS-DELIMITER-INFO. 05 WS-DELIMITER OCCURS 10 TIMES PIC X(5). 01 WS-PROCESSING-COUNTERS. 05 WS-ITEM-COUNT PIC 9(2). 05 WS-CURRENT-POINTER PIC 9(3). PROCEDURE DIVISION. MULTIPLE-DELIMITER-DEMO. DISPLAY "=== Multiple Delimiters Demo ===" *> Example: Mixed delimiters (comma, semicolon, pipe) MOVE "Apple,Orange;Banana|Grape,Cherry;Mango|Peach" TO WS-COMPLEX-STRING UNSTRING WS-COMPLEX-STRING DELIMITED BY "," OR ";" OR "|" INTO WS-ITEM(1), WS-ITEM(2), WS-ITEM(3), WS-ITEM(4), WS-ITEM(5), WS-ITEM(6), WS-ITEM(7), WS-ITEM(8) DELIMITER IN WS-DELIMITER(1), WS-DELIMITER(2), WS-DELIMITER(3), WS-DELIMITER(4), WS-DELIMITER(5), WS-DELIMITER(6), WS-DELIMITER(7), WS-DELIMITER(8) TALLYING IN WS-ITEM-COUNT WITH POINTER WS-CURRENT-POINTER END-UNSTRING DISPLAY "Mixed delimiter parsing results:" PERFORM VARYING WS-INDEX FROM 1 BY 1 UNTIL WS-INDEX > WS-ITEM-COUNT DISPLAY "Item " WS-INDEX ": '" WS-ITEM(WS-INDEX) "'" IF WS-INDEX < WS-ITEM-COUNT DISPLAY " Delimiter: '" WS-DELIMITER(WS-INDEX) "'" END-IF END-PERFORM DISPLAY "Total items: " WS-ITEM-COUNT DISPLAY "Final pointer position: " WS-CURRENT-POINTER.

STRING with DELIMITED BY

Building Delimited Strings

cobol
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
DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-SOURCE-FIELDS. 05 WS-FIRST-NAME PIC X(15) VALUE "John". 05 WS-LAST-NAME PIC X(20) VALUE "Doe". 05 WS-AGE PIC X(3) VALUE "30". 05 WS-DEPARTMENT PIC X(10) VALUE "IT". 05 WS-SALARY PIC X(8) VALUE "75000". 01 WS-OUTPUT-STRINGS. 05 WS-CSV-STRING PIC X(200). 05 WS-PIPE-STRING PIC X(200). 05 WS-FORMATTED-STRING PIC X(200). 01 WS-STRING-POINTER PIC 9(3). PROCEDURE DIVISION. STRING-BUILDING-DEMO. DISPLAY "=== STRING with DELIMITED BY Demo ===" *> Build CSV format MOVE 1 TO WS-STRING-POINTER STRING WS-FIRST-NAME DELIMITED BY SPACE "," DELIMITED BY SIZE WS-LAST-NAME DELIMITED BY SPACE "," DELIMITED BY SIZE WS-AGE DELIMITED BY SPACE "," DELIMITED BY SIZE WS-DEPARTMENT DELIMITED BY SPACE "," DELIMITED BY SIZE WS-SALARY DELIMITED BY SPACE INTO WS-CSV-STRING WITH POINTER WS-STRING-POINTER END-STRING DISPLAY "CSV Format: '" WS-CSV-STRING "'" DISPLAY "CSV Length: " WS-STRING-POINTER - 1 *> Build pipe-separated format MOVE 1 TO WS-STRING-POINTER STRING WS-FIRST-NAME DELIMITED BY SPACE "|" DELIMITED BY SIZE WS-LAST-NAME DELIMITED BY SPACE "|" DELIMITED BY SIZE WS-AGE DELIMITED BY SPACE "|" DELIMITED BY SIZE WS-DEPARTMENT DELIMITED BY SPACE "|" DELIMITED BY SIZE WS-SALARY DELIMITED BY SPACE INTO WS-PIPE-STRING WITH POINTER WS-STRING-POINTER END-STRING DISPLAY "Pipe Format: '" WS-PIPE-STRING "'" DISPLAY "Pipe Length: " WS-STRING-POINTER - 1 *> Build formatted string with different delimiters MOVE 1 TO WS-STRING-POINTER STRING "Name: " DELIMITED BY SIZE WS-FIRST-NAME DELIMITED BY SPACE " " DELIMITED BY SIZE WS-LAST-NAME DELIMITED BY SPACE "; Age: " DELIMITED BY SIZE WS-AGE DELIMITED BY SPACE "; Dept: " DELIMITED BY SIZE WS-DEPARTMENT DELIMITED BY SPACE INTO WS-FORMATTED-STRING WITH POINTER WS-STRING-POINTER END-STRING DISPLAY "Formatted: '" WS-FORMATTED-STRING "'".

Dynamic String Construction

cobol
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
DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-DYNAMIC-FIELDS. 05 WS-FIELD-DATA OCCURS 5 TIMES PIC X(20). 05 WS-FIELD-COUNT PIC 9(1) VALUE 5. 01 WS-DELIMITERS. 05 WS-COMMA PIC X(1) VALUE ",". 05 WS-SEMICOLON PIC X(1) VALUE ";". 05 WS-PIPE PIC X(1) VALUE "|". 05 WS-TAB PIC X(1) VALUE X"09". 01 WS-DYNAMIC-OUTPUT. 05 WS-RESULT-STRING PIC X(300). 05 WS-TEMP-STRING PIC X(300). 01 WS-CONTROLS. 05 WS-DELIMITER-CHOICE PIC X(1). 05 WS-CURRENT-DELIMITER PIC X(1). 05 WS-OUTPUT-POINTER PIC 9(3). PROCEDURE DIVISION. DYNAMIC-STRING-DEMO. DISPLAY "=== Dynamic String Construction ===" *> Initialize sample data MOVE "Product1" TO WS-FIELD-DATA(1) MOVE "Product2" TO WS-FIELD-DATA(2) MOVE "Product3" TO WS-FIELD-DATA(3) MOVE "Product4" TO WS-FIELD-DATA(4) MOVE "Product5" TO WS-FIELD-DATA(5) *> Get delimiter choice DISPLAY "Choose delimiter (1=Comma, 2=Semicolon, 3=Pipe, 4=Tab): " ACCEPT WS-DELIMITER-CHOICE PERFORM DETERMINE-DELIMITER PERFORM BUILD-DYNAMIC-STRING DISPLAY "Result: '" WS-RESULT-STRING "'". DETERMINE-DELIMITER. EVALUATE WS-DELIMITER-CHOICE WHEN "1" MOVE WS-COMMA TO WS-CURRENT-DELIMITER DISPLAY "Using comma delimiter" WHEN "2" MOVE WS-SEMICOLON TO WS-CURRENT-DELIMITER DISPLAY "Using semicolon delimiter" WHEN "3" MOVE WS-PIPE TO WS-CURRENT-DELIMITER DISPLAY "Using pipe delimiter" WHEN "4" MOVE WS-TAB TO WS-CURRENT-DELIMITER DISPLAY "Using tab delimiter" WHEN OTHER MOVE WS-COMMA TO WS-CURRENT-DELIMITER DISPLAY "Default: Using comma delimiter" END-EVALUATE. BUILD-DYNAMIC-STRING. MOVE SPACES TO WS-RESULT-STRING MOVE 1 TO WS-OUTPUT-POINTER PERFORM VARYING WS-INDEX FROM 1 BY 1 UNTIL WS-INDEX > WS-FIELD-COUNT *> Add the field data STRING WS-FIELD-DATA(WS-INDEX) DELIMITED BY SPACE INTO WS-RESULT-STRING WITH POINTER WS-OUTPUT-POINTER END-STRING *> Add delimiter if not the last field IF WS-INDEX < WS-FIELD-COUNT STRING WS-CURRENT-DELIMITER DELIMITED BY SIZE INTO WS-RESULT-STRING WITH POINTER WS-OUTPUT-POINTER END-STRING END-IF END-PERFORM.

Advanced DELIMITED BY Techniques

File Processing with Delimiters

cobol
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
ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT INPUT-FILE ASSIGN TO "DATA.CSV" ORGANIZATION IS SEQUENTIAL FILE STATUS IS FILE-STATUS-INPUT. SELECT OUTPUT-FILE ASSIGN TO "PROCESSED.TXT" ORGANIZATION IS SEQUENTIAL FILE STATUS IS FILE-STATUS-OUTPUT. DATA DIVISION. FILE SECTION. FD INPUT-FILE. 01 INPUT-RECORD PIC X(200). FD OUTPUT-FILE. 01 OUTPUT-RECORD PIC X(300). WORKING-STORAGE SECTION. 01 FILE-STATUS-INPUT PIC X(2). 01 FILE-STATUS-OUTPUT PIC X(2). 01 WS-EOF-FLAG PIC X(1) VALUE 'N'. 01 WS-CSV-FIELDS. 05 WS-CUSTOMER-ID PIC X(10). 05 WS-CUSTOMER-NAME PIC X(30). 05 WS-AMOUNT PIC X(12). 05 WS-DATE PIC X(10). 05 WS-STATUS PIC X(10). 01 WS-PROCESSING-COUNTERS. 05 WS-RECORDS-READ PIC 9(5) VALUE 0. 05 WS-RECORDS-PROCESSED PIC 9(5) VALUE 0. 05 WS-FIELD-COUNT PIC 9(1). PROCEDURE DIVISION. FILE-PROCESSING-DEMO. DISPLAY "=== File Processing with Delimiters ===" OPEN INPUT INPUT-FILE OPEN OUTPUT OUTPUT-FILE PERFORM PROCESS-CSV-FILE UNTIL WS-EOF-FLAG = 'Y' CLOSE INPUT-FILE, OUTPUT-FILE DISPLAY "Processing complete:" DISPLAY "Records read: " WS-RECORDS-READ DISPLAY "Records processed: " WS-RECORDS-PROCESSED. PROCESS-CSV-FILE. READ INPUT-FILE AT END MOVE 'Y' TO WS-EOF-FLAG NOT AT END ADD 1 TO WS-RECORDS-READ PERFORM PARSE-CSV-RECORD IF WS-FIELD-COUNT = 5 PERFORM FORMAT-OUTPUT-RECORD ADD 1 TO WS-RECORDS-PROCESSED ELSE DISPLAY "Invalid record format: " INPUT-RECORD END-IF END-READ. PARSE-CSV-RECORD. INITIALIZE WS-CSV-FIELDS UNSTRING INPUT-RECORD DELIMITED BY "," INTO WS-CUSTOMER-ID, WS-CUSTOMER-NAME, WS-AMOUNT, WS-DATE, WS-STATUS TALLYING IN WS-FIELD-COUNT ON OVERFLOW DISPLAY "Overflow parsing record: " INPUT-RECORD END-UNSTRING. FORMAT-OUTPUT-RECORD. STRING "Customer: " DELIMITED BY SIZE WS-CUSTOMER-NAME DELIMITED BY SPACE " | ID: " DELIMITED BY SIZE WS-CUSTOMER-ID DELIMITED BY SPACE " | Amount: $" DELIMITED BY SIZE WS-AMOUNT DELIMITED BY SPACE " | Date: " DELIMITED BY SIZE WS-DATE DELIMITED BY SPACE " | Status: " DELIMITED BY SIZE WS-STATUS DELIMITED BY SPACE INTO OUTPUT-RECORD END-STRING WRITE OUTPUT-RECORD.

Complex Delimiter Handling

cobol
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
DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-COMPLEX-DATA PIC X(500). 01 WS-QUOTE-DELIMITED-FIELDS. 05 WS-QUOTED-FIELD OCCURS 10 TIMES PIC X(50). 01 WS-ESCAPE-HANDLING. 05 WS-TEMP-FIELD PIC X(100). 05 WS-CLEAN-FIELD PIC X(100). 01 WS-PARSING-CONTROLS. 05 WS-IN-QUOTES PIC X(1) VALUE 'N'. 05 WS-QUOTE-COUNT PIC 9(2) VALUE 0. 05 WS-FIELD-INDEX PIC 9(2) VALUE 1. 05 WS-CHAR-POINTER PIC 9(3) VALUE 1. PROCEDURE DIVISION. COMPLEX-DELIMITER-DEMO. DISPLAY "=== Complex Delimiter Handling ===" *> Example with quoted fields containing delimiters MOVE '"John, Jr.",25,"Software Engineer","New York, NY","Active"' TO WS-COMPLEX-DATA PERFORM PARSE-QUOTED-CSV PERFORM DISPLAY-PARSED-RESULTS. PARSE-QUOTED-CSV. *> Handle CSV with quoted fields that may contain commas MOVE 1 TO WS-CHAR-POINTER MOVE 1 TO WS-FIELD-INDEX MOVE SPACES TO WS-TEMP-FIELD PERFORM UNTIL WS-CHAR-POINTER > LENGTH OF WS-COMPLEX-DATA IF WS-COMPLEX-DATA(WS-CHAR-POINTER:1) = '"' IF WS-IN-QUOTES = 'N' MOVE 'Y' TO WS-IN-QUOTES ADD 1 TO WS-QUOTE-COUNT ELSE MOVE 'N' TO WS-IN-QUOTES ADD 1 TO WS-QUOTE-COUNT END-IF ELSE IF WS-COMPLEX-DATA(WS-CHAR-POINTER:1) = "," IF WS-IN-QUOTES = 'N' *> End of field - store it PERFORM STORE-CURRENT-FIELD MOVE SPACES TO WS-TEMP-FIELD ADD 1 TO WS-FIELD-INDEX ELSE *> Comma inside quotes - part of field data PERFORM ADD-CHAR-TO-FIELD END-IF ELSE PERFORM ADD-CHAR-TO-FIELD END-IF ADD 1 TO WS-CHAR-POINTER END-PERFORM *> Store the last field IF WS-TEMP-FIELD NOT = SPACES PERFORM STORE-CURRENT-FIELD END-IF. ADD-CHAR-TO-FIELD. STRING WS-TEMP-FIELD DELIMITED BY SPACE WS-COMPLEX-DATA(WS-CHAR-POINTER:1) DELIMITED BY SIZE INTO WS-TEMP-FIELD END-STRING. STORE-CURRENT-FIELD. IF WS-FIELD-INDEX <= 10 MOVE WS-TEMP-FIELD TO WS-QUOTED-FIELD(WS-FIELD-INDEX) DISPLAY "Field " WS-FIELD-INDEX ": '" WS-QUOTED-FIELD(WS-FIELD-INDEX) "'" END-IF. DISPLAY-PARSED-RESULTS. DISPLAY " " DISPLAY "Parsing Results:" DISPLAY "Total quotes found: " WS-QUOTE-COUNT DISPLAY "Fields extracted: " WS-FIELD-INDEX - 1 PERFORM VARYING WS-INDEX FROM 1 BY 1 UNTIL WS-INDEX >= WS-FIELD-INDEX DISPLAY "Field " WS-INDEX ": '" WS-QUOTED-FIELD(WS-INDEX) "'" END-PERFORM.

Best Practices and Guidelines

DELIMITED BY Best Practices

  • Always use TALLYING to track the number of fields parsed
  • Handle overflow conditions with ON OVERFLOW clauses
  • Use DELIMITER IN to capture actual delimiter characters
  • Initialize receiving fields before UNSTRING operations
  • Consider using WITH POINTER for precise string positioning
  • Test with edge cases like empty fields and missing delimiters
  • Handle quoted fields that may contain delimiter characters

Common Patterns

cobol
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
*> Standard UNSTRING pattern UNSTRING source-string DELIMITED BY delimiter INTO field-1, field-2, field-3 TALLYING IN field-count ON OVERFLOW DISPLAY "Too many fields in input" END-UNSTRING *> Multiple delimiter pattern UNSTRING input-data DELIMITED BY "," OR ";" OR "|" INTO data-field-1, data-field-2, data-field-3 DELIMITER IN delim-1, delim-2, delim-3 TALLYING IN field-count END-UNSTRING *> STRING building pattern STRING field-1 DELIMITED BY SPACE "," DELIMITED BY SIZE field-2 DELIMITED BY SPACE "," DELIMITED BY SIZE field-3 DELIMITED BY SPACE INTO output-string WITH POINTER string-pointer END-STRING

Frequently Asked Questions