虽然超出了要求,但该程序应该可以处理大多数 CSV 记录。它没有使用制表符分隔符进行测试。该程序将 CSV 文本(删除添加的引号)从由选定分隔符分隔的分隔符转换为由 LOW-VALUES 分隔的分隔符。使用UNSTRING ... DELIMITED LOW-VALUES INTO ... 更容易分隔字段。
IDENTIFICATION DIVISION.
PROGRAM-ID. CSV2STR.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 I COMP PIC 9(4).
01 J COMP PIC 9(4).
01 FLD-START COMP PIC 9(4).
01 STATE COMP PIC 9(4).
01 FLD-SEP PIC X VALUE LOW-VALUES.
01 QUOT PIC X VALUE """".
01 APOS PIC X VALUE "'".
01 COMM PIC X VALUE ",".
LINKAGE SECTION.
01 INPUT-REC PIC X(2000).
01 INPUT-LENGTH COMP PIC 9(4).
01 OUTPUT-REC PIC X(2000).
01 OUTPUT-LENGTH COMP PIC 9(4).
01 DELIM PIC X.
PROCEDURE DIVISION USING INPUT-REC INPUT-LENGTH
OUTPUT-REC OUTPUT-LENGTH DELIM.
BEGIN.
IF INPUT-LENGTH = 0 OR > 2000
MOVE 0 TO OUTPUT-LENGTH
EXIT PROGRAM
END-IF
IF DELIM NOT = SPACE
MOVE DELIM TO COMM
ELSE
MOVE "," TO COMM
END-IF
PERFORM CONVERT-RECORD
SUBTRACT 1 FROM J GIVING OUTPUT-LENGTH
EXIT PROGRAM
.
CONVERT-RECORD.
MOVE 1 TO STATE I J FLD-START
PERFORM CONVERT-RECORD-PROC
UNTIL I > INPUT-LENGTH
MOVE FLD-SEP TO OUTPUT-REC (J:1)
*> FOR NO FIELD AFTER THE LAST DELIMITER
IF INPUT-REC (I - 1:1) = COMM
ADD 1 TO J
MOVE FLD-SEP TO OUTPUT-REC (J:1)
END-IF
.
CONVERT-RECORD-PROC.
*> CSV-DT
EVALUATE STATE
ALSO I = FLD-START
ALSO INPUT-REC (I:1)
ALSO INPUT-REC (I + 1:1)
*> RULE 1 DETERMINES IF FIELD BEGINS WITH QUOTE
WHEN 1 ALSO TRUE ALSO QUOT ALSO ANY
MOVE 2 TO STATE
ADD 1 TO I
*> RULE 2 SPECIAL CASE OF SPACE + APOSTROPHE AT FIELD START
WHEN 1 ALSO TRUE ALSO SPACE ALSO APOS
ADD 1 TO I
*> RULE 3 COPIES ONE CHARACTER
WHEN 1 ALSO ANY ALSO NOT COMM ALSO ANY
MOVE INPUT-REC (I:1) TO OUTPUT-REC (J:1)
ADD 1 TO I
ADD 1 TO J
*> RULE 4 ENDS A FIELD
WHEN 1 ALSO ANY ALSO COMM ALSO ANY
MOVE FLD-SEP TO OUTPUT-REC (J:1)
ADD 1 TO I
ADD 1 TO J
MOVE I TO FLD-START
*> RULE 5 FOR QUOTED FIELD DROPS INITAL QUOTE
WHEN 2 ALSO ANY ALSO NOT QUOT ALSO ANY
MOVE INPUT-REC (I:1) TO OUTPUT-REC (J:1)
ADD 1 TO I
ADD 1 TO J
*> RULE 6 FOR QUOTED FIELD CONVERTS TWO QUOTED TO ONE
WHEN 2 ALSO ANY ALSO QUOT ALSO QUOT
MOVE QUOTE TO OUTPUT-REC (J:1)
ADD 2 TO I
ADD 1 TO J
*> RULE 7 FOR QUOTED FIELD DROPS QUOTE BEFORE DELIMITER
WHEN 2 ALSO ANY ALSO QUOT ALSO COMM
MOVE FLD-SEP TO OUTPUT-REC (J:1)
ADD 2 TO I
ADD 1 TO J
MOVE I TO FLD-START
MOVE 1 TO STATE
*> RULE 8 FOR QUOTED FIELD DROPS FINAL QUOTE OF LAST FIELD
WHEN 2 ALSO ANY ALSO QUOT ALSO SPACE
ADD 2 TO I
ADD 1 TO J
MOVE I TO FLD-START
MOVE 1 TO STATE
END-EVALUATE
.
测试了以下 CSV 文件:
120,ABC,123,"12"" RULER","""ABC"", ""DEF"", ""GHI""", 'ABC',"123,456"
"""789""",,,,"""mno""",,
测试程序输出:
1: 120
2: ABC
3: 123
4: 12" RULER
5: "ABC", "DEF", "GHI"
6: 'ABC'
7: 123,456
1: "789"
2:
3:
4:
5: "mno"
6:
7: