REXX — парсинг из CSV-файла

У меня возникли проблемы с анализом CSV из текстового файла, и мне было интересно, не могли бы вы, ребята, мне помочь. Пока у меня есть следующее,

Файл CSV (DATA.txt) выглядит примерно так, в нем всегда будет 15 полей, разделенных запятой. Не все поля являются обязательными, поэтому некоторые из них будут заполнены, а некоторые останутся пустыми.

Seattle,Lastname,Firstname,DOB,SEX,etc,etc
Seattle,Lastname,Firstname,DOB,,etc,etc
Portland,Lastname,Firstname,DOB,SEX,,,etc
Portland,Lastname,Firstname,DOB,SEX,etc,etc

А вот и мой код REXX

SOURCEFILE = "C:\DATA\DATA.TXT"
IF A=2 THEN DO COUNTER=1 TO LINES(SOURCEFILE)
    PARSE VALUE LINEIN(SOURCEFILE) WITH CITY "," LAST_NAME "," FIRST_NAME "," MOM_NAME "," MIDDLE_NAME "," DAD_NAME "," DOB "," etc "," etc "," etc "," etc "," SEX "," etc "," etc
    CALL SETCURSOR 4,23
    CALL CREATEDATA
END

CREATEDATA:
CALL TYPE CITY
CALL PRESS TAB
CALL TYPE LAST_NAME
CALL PRESS TAB
CALL TYPE DATE(U)
CALL PRESS TAB
CALL TYPE FIRST_NAME
CALL PRESS TAB
CALL PRESS ENTER
RETURN

Я не уверен, следует ли мне использовать ARG или VAR при синтаксическом анализе или я правильно написал первые две строки. Я точно знаю, что моя функция CREATEDATA работает правильно, потому что я получаю введенное "CITY", но не проанализированное значение. Любая помощь будет очень высоко ценится. Благодарю вас!


person user2267512    schedule 10.04.2013    source источник


Ответы (2)


Несколько комментариев:

1) Lines(SourceFile) в системе Windows, вероятно, включает чтение всего файла для подсчета последовательностей CR-LF. Затем ваш цикл Parse value LineIn(SourceFile) снова читает его. Типичный способ Rexx сделать это:

Address SYSTEM 'TYPE' SourceFile with output stem Lines.
Do Counter = 1 to Lines.0
    Parse var Lines.Counter ...
End
Drop Lines.

По крайней мере, пока файл не настолько велик, что хранение его в массиве дорого обходится в памяти.

2) Вы стекаете в CreateData в конце цикла, поэтому вы видите "CITY". Вам нужна Return или Exit после этой инструкции End.

3) В свете #2 очевидно, что Parse никогда не выполняется, потому что City не инициализирована (значением неинициализированной переменной в Rexx является ее имя в верхнем регистре). Это зависит от A=2, чего не должно быть.

person Ross Patterson    schedule 10.04.2013
comment
Согласно книге Cowlishaw's Rexx, встроенная функция LINES может возвращать количество строк в файле, на который указывает ссылка, или, если это невозможно определить, «1», где подходящим является ненулевое количество, в противном случае «0». Я довольно часто использую ooRexx в Windows и могу подтвердить, что ooRexx не считает все строки, а просто возвращает 0/1. Я использую следующее для чтения файлов по одной строке за раз: DO WHILE LINES(имя файла) › 0; PARSE VALUE LINEIN(имя файла) с... ; КОНЕЦ - person NealB; 12.04.2013
comment
Результат Lines() зависит от реализации. Некоторые реализации возвращают количество, другие просто 1 или 0, как вы заметили. Вот почему я предпочитаю загружать стебель вверх: Lines.0 — это фактический счет. - person Ross Patterson; 13.04.2013

Один вопрос, какова цель, если A = 2, то в

IF A=2 THEN DO COUNTER=1 TO LINES(SOURCEFILE)

если A != 2, цикл пропускается. Я подозреваю, что ваша программа должна быть:

SOURCEFILE = "C:\DATA\DATA.TXT"
DO COUNTER=1 TO LINES(SOURCEFILE) 
    PARSE VALUE LINEIN(SOURCEFILE) WITH CITY "," LAST_NAME "," FIRST_NAME "," MOM_NAME "," MIDDLE_NAME "," DAD_NAME "," DOB "," etc "," etc "," etc "," etc "," SEX "," etc "," etc
    CALL SETCURSOR 4,23
    CALL CREATEDATA
END

RETURN   /* prevent the fall through to createdata */

CREATEDATA:




---------------------------

Оператор разбора имеет следующий базовый формат

parse [источник] [parse-control]

где [источник] включает

arg — аргументы при вызове процедуры pull — данные извлекаются из стека var — данные берутся из значения переменной ... со встроенными данными

Таким образом, ваш анализ может быть выполнен как

   linein = LINEIN(SOURCEFILE)
   PARSE var linein CITY "," LAST_NAME "," FIRST_NAME "," MOM_NAME "," MIDDLE_NAME "," DAD_NAME "," DOB "," etc "," etc "," etc "," etc "," SEX "," etc "," etc

or

    DO COUNTER=1 TO LINES(SOURCEFILE) 
        CALL SETCURSOR 4,23
        CALL CREATEDATA LINEIN(SOURCEFILE)
    END

    RETURN   /* prevent the fall through to createdata */

    CREATEDATA:
    parse arg CITY "," LAST_NAME "," FIRST_NAME "," MOM_NAME "," MIDDLE_NAME "," DAD_NAME "," DOB "," etc "," etc "," etc "," etc "," SEX "," etc "," etc

В конце концов, задница Росс сказала, что вам следует попробовать избегать строк (исходный файл), так как это связано с чтением всего файла.

person Bruce Martin    schedule 11.04.2013