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.
DELIMITED BY is primarily used with UNSTRING and STRING statements to control how data is parsed or concatenated based on delimiter characters.
12345678910111213141516*> 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
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253DATA 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.
12345678910111213141516171819202122232425262728293031323334353637383940DATA 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.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071DATA 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 "'".
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081DATA 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.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293ENVIRONMENT 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.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485DATA 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.
1234567891011121314151617181920212223242526*> 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