Проблемы при обработке нулей, найденных во входном файле CSV с Perl - PullRequest
1 голос
/ 09 февраля 2020

Друзья:

Я должен обработать файл CSV, используя язык Perl, и создать Excel в качестве вывода, используя модуль Excel :: Writer :: XSLX. Это не домашнее задание, а реальная проблема, когда я не могу загрузить какую-либо Perl версию (на самом деле мне нужно использовать Perl 5.6) или какой-либо Perl модуль (у меня их ограниченный набор). Моя ОС UNIX. Я также могу использовать (встраивание в Perl) k sh и csh (с некоторыми ограничениями, как я обнаружил до сих пор). Пожалуйста, ограничьте ваши ответы доступными мне инструментами. Заранее спасибо!

Несмотря на то, что я не Perl разработчик, но из других языков я уже сделал свою работу. Однако заказчик требует дополнительной обработки, в которой я застреваю.

1) Камни на дороге, которую я обнаружил, поступают с двух сторон: из Perl и из Excel в конкретных стилях обработки данных. Я уже нашел обходной путь для работы с Excel, но - как уже упоминалось в теме - у меня возникают трудности при обработке нулей, найденных во входном файле CSV. Для работы с Excel я использую способ '0, который является последним способом представления данных, который, как представляется, Excel при использовании стиля форматирования @.

2) Сценарий:

Мне нужно отловить отдельные нули, которые могут присутствовать в любой строке / столбце / ячейке входного файла CSV, и поместить их как таковые (нули) в выходной файл Excel.

Я получу go напрямую на мой вопрос, чтобы не потерять ваше драгоценное время. После моего вопроса я предоставляю более подробную информацию:

Исследование и вопрос:

  • Я пытался использовать регулярное выражение Perl, чтобы найти автономное "0" и заменить их любой строкой, планируя заменить их обратно на «0» в конце обработки.
perl -p -i -e 's/\b0\b/string/g' myfile.csv`

и

perl -i -ple 's/\b0\b/string/g'  myfile.csv

Работают; но только из командной строки. Они не работают, когда я вызываю их из сценария Perl следующим образом:

system("perl -i -ple 's/\b0\b/string/g' myfile.csv")

Не знаю почему ... Я уже пытался использовать exec и eval вместо system, с теми же результатами.

Обратите внимание, что у меня есть тонна регулярных выражений, которые прекрасно работают с такой же структурой, например:

system("perl -i -ple 's/input/output/g' myfile.csv")

Я также пытался использовать обратные ссылки и qx//, без успеха. Обратите внимание, что qx// и обратные пометки имеют не одинаковое поведение, так как qx// жалуется на границы \ b из-за прямого слэ sh.

Я пытался использовать sed -i, но моя система отклоняет -i как недопустимый флаг (не знаю, происходит ли это во всех UNIX, но, по крайней мере, это происходит в рабочем состоянии. Однако принимает perl -i).

Я пробовал встраивать awk (который работает из командной строки), таким образом:

system `awk -F ',' -v OFS=','  '$1 == \"0\" { $1 = "string" }1' myfile.csv > myfile_copy.csv

Но это работает только для первого столбца (в командной строке) и, кроме недостатка наличия дополнительного файла копии, Perl жалуется на перенаправление >, предполагая, что оно "больше чем" ...

system(q@awk 'BEGIN{FS=OFS=",";split("1 2 3 4 5",A," ") } { for(i in A)sub(0,"string",$A[i] ) }1' myfile.csv@);

Это awk работает из командной строки, но только 5 столбцов. Но не в Perl с использованием @.

Все комбинации exec и eval также были протестированы безуспешно.

Я также пытался перейти на system каждый из awk компонентов, в качестве аргументов, разделенных запятыми, но не нашел какого-либо действительного способа передать редиректор (>), поскольку Perl отклоняет его по указанной причине.

Используя другой подход, я заметил, что «автономные нули» кажутся «проглоченными» модулем Text :: CSV, таким образом, я избавился от него и вернулся к традиционному циклу в csv строка за строкой и разделитель запятых, сохраняя нули таким образом. Однако я обнаружил «тайну» isdual в Perl, и из-за ограниченности имеющихся у меня модулей я не могу использовать Dumper. Затем я также исследовал возможности двоичных файлов в Perl и попробовал $x ^ $x, который устарел с версии 5.22, но действителен до этой версии (я сказал, что у меня 5.6). Это полезно, чтобы ловить числа против строк. Однако, в то время как if( $x ^ $x ) возвращает TRUE для строк, if( !( $x ^ $x ) ) не возвращает TRUE при $x = 0. [ОБНОВЛЕНИЕ: Я попробовал это в выделенном Perl сценарии, просто для этой цели, и он работает. Я считаю, что мое вероятное неправильное заключение («не возвращать ИСТИНА») было получено, когда я все еще не осознавал, что Text :: CSV поглощал мои нули. Выполняю новые тесты ...].

Я буду очень признателен за вашу помощь!

БОЛЬШЕ ДЕТАЛЕЙ ПО МОИМ ТРЕБОВАНИЯМ:

1) Это динамический отчет c, поступающий из базы данных, который передается мне, и я программно забираю из папки. Dynami c означает, что в нем может быть любое количество таблиц, какое количество столбцов в каждой таблице, какие имена называются заголовками столбцов, какое количество строк в каждой таблице.

2) Я не знаю, и не может знать, имена столбцов, потому что они варьируются от отчета к отчету. Поэтому я не могу ориентироваться на имена столбцов.

Пример ввода:

Alfa,Alfa1,Beta,Gamma,Delta,Delta1,Epsilon,Dseta,Heta,Zeta,Iota,Kappa
0,J5,alfa,0,111.33,124.45,0,0,456.85,234.56,798.43,330000.00
M1,0,X888,ZZ,222.44,111.33,12.24,45.67,0,234.56,0,975.33

3) Ввод Объяснение

a) Это пример случайного отчета с 12 столбцов и 3 ряда. Первая строка - это заголовок.

b) Я называю "автономные нули" теми "чистыми" нулями, которые появляются в файле CSV, начиная со второй строки, между запятыми, как 0, (если это случай первая позиция в строке) или как ,0, в последующих позициях.

c) Во второй строке примера вы можете прочитать, с начала строки: 0,J5,alfa,0, что в этом Частным случаем являются «слова» или «строки». В этом случае 4 имени (обратите внимание, что два из них являются нулями, которые должны рассматриваться как строки ). Таким образом, у нас есть пример с 4 именами столбцов (Alfa,Alfa1,Beta,Gamma - заголовки для этих столбцов, но только в этом сценарии). Начиная с этой точки, во втором ряду вы можете видеть числа с плавающей запятой (* .00) и среди них вы можете видеть 2 нуля, которые являются числами . Наконец, в третьей строке вы можете прочитать M1,0,X888,Z, которые являются именами для первых 4 столбцов. Обратите внимание, что в 4-м столбце второй строки в качестве имени указано 0, а в 4-м столбце третьей строки - в качестве имени ZZ.

Сводка. Таблица-отчет разделена на 2 части, слева направо: 4 столбца для имен и 8 столбцов для чисел. Всегда первые M столбцов являются именами, а последние N столбцов являются числами. - Неизвестно, какое число равно М: какое количество столбцов, выделенных для слов / строк, я получу. - Неизвестно, какое число N: какое количество столбцов, посвященных номерам, я получу. - ИЗВЕСТНО, что после того, как количество столбцов M заканчивается, всегда начинается N, и это постоянно для всех строк.

1 Ответ

1 голос
/ 10 февраля 2020

Я провел быстрое исследование Perl границ для регулярных выражений (\b), и я не нашел никакой соответствующей информации относительно того, применимо это или нет в Perl 5.6.

Однако, поскольку вы используете старую версию Perl, попробуйте традиционный стиль UNIX / Linux (я имею в виду, что Perl наследует от Shell), например:

system("perl -i -ple 's/^0/string/g' myfile.csv");

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

Или, может быть, лучше (если у вас есть эти "автономные" нули и вы хотите избегайте любых нежелательных изменений в какой-либо строке «ведущих нулей»):

system("perl -i -ple 's/^0,/string,/g' myfile.csv");

[Обратите внимание, что я добавил запятую после нуля; и, конечно же, после строки].

Обратите внимание, что первое регулярное выражение должно работать; второй - просто «предостережение», чтобы быть осторожным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...