Perl — пропущенная запятая на выходе

#perl

#perl

Вопрос:

У меня есть обновление в моем скрипте для форматирования файла и удаления лишней запятой на основе поля DOE J, в некоторых моих строках есть лишняя, а в некоторых нет. Я заставил это работать, но проблема, с которой я сейчас сталкиваюсь, заключается в том, что мне не хватает одной из моих запятых, и я не уверен, почему это происходит.

   while(<IN>) {
        my $line = $_;
    $line =~ s/^(([^,] ,){13})([^,]*),*([^,]*)(,[^,] ,.*)$/1345/;
        print OUT "$line";
  }
  

ВВОД:

 555555,Service Location,06/30,210,OD44000,07/01/2011,09/01/2000,09/04/2000,1,07/01/2000,04/18/2000,2000-06-23 00:00:00,2000-07-01 00:00:00,DOE, J,11950000,349000,200000000A,07/13/2000,2000-07-27 00:00:00,20010002000600CAA,8,1, ,6,Yes,,No,,No,01001,2800038000,**SUM**,0,400,38648.44,0,,,,,,,,,,,,,,,,,6018.32,0,0,0,0,,,6018.32,0,0,0,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0
555555,Service Location,06/30,210,OD44000,07/01/2011,09/01/2000,09/04/2000,1,07/01/2000,04/18/2000,2000-06-23 00:00:00,2000-07-01 00:00:00,DOE J,11950000,349000,200000000A,07/13/2000,2000-07-27 00:00:00,20010002000600CAA,8,1, ,6,Yes,,No,,No,01001,2800038000,**SUM**,0,400,38648.44,0,,,,,,,,,,,,,,,,,6018.32,0,0,0,0,,,6018.32,0,0,0,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0
  

ВЫВОД:

 555555,Service Location,06/30,210,OD44000,07/01/2011,09/01/2000,09/04/2000,1,07/01/2000,04/18/2000,2000-06-23 00:00:00,2000-07-01 00:00:00,DOE J,11950000,349000,200000000A,07/13/2000,2000-07-27 00:00:00,20010002000600CAA,8,1, ,6,Yes,,No,,No,01001,2800038000,**SUM**,0,400,38648.44,0,,,,,,,,,,,,,,,,,6018.32,0,0,0,0,,,6018.32,0,0,0,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0
555555,Service Location,06/30,210,OD44000,07/01/2011,09/01/2000,09/04/2000,1,07/01/2000,04/18/2000,2000-06-23 00:00:00,2000-07-01 00:00:00,DOE J11950000,349000,200000000A,07/13/2000,2000-07-27 00:00:00,20010002000600CAA,8,1, ,6,Yes,,No,,No,01001,2800038000,**SUM**,0,400,38648.44,0,,,,,,,,,,,,,,,,,6018.32,0,0,0,0,,,6018.32,0,0,0,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0
  

Ожидаемый результат:

 555555,Service Location,06/30,210,OD44000,07/01/2011,09/01/2000,09/04/2000,1,07/01/2000,04/18/2000,2000-06-23 00:00:00,2000-07-01 00:00:00,DOE J,11950000,349000,200000000A,07/13/2000,2000-07-27 00:00:00,20010002000600CAA,8,1, ,6,Yes,,No,,No,01001,2800038000,**SUM**,0,400,38648.44,0,,,,,,,,,,,,,,,,,6018.32,0,0,0,0,,,6018.32,0,0,0,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0
555555,Service Location,06/30,210,OD44000,07/01/2011,09/01/2000,09/04/2000,1,07/01/2000,04/18/2000,2000-06-23 00:00:00,2000-07-01 00:00:00,DOE J,11950000,349000,200000000A,07/13/2000,2000-07-27 00:00:00,20010002000600CAA,8,1, ,6,Yes,,No,,No,01001,2800038000,**SUM**,0,400,38648.44,0,,,,,,,,,,,,,,,,,6018.32,0,0,0,0,,,6018.32,0,0,0,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0
  

Комментарии:

1. Все это * , одно за другим, довольно неприятно отслеживать в уме; они позволяют сопоставлять некоторые довольно неожиданные шаблоны. Можете ли вы объяснить словами, как предполагается проводить различие между DOE, J, ... и DOE J, ... ? (Оба они содержат строки, за которыми следуют запятые.) Я не могу понять из вашего кода, как он должен отличать их друг от друга. ( DOE,J Нужно исправить, верно?)

2. ( Это всегда строки DOE и J ? Я предполагаю, что вместо этого могут быть другие слова. Всегда ли речь идет о полях 13-и, возможно, 14, в виде текста с цифрами в полях прямо перед и после них? Фиксировано ли общее количество полей во всей строке? и т.д. …)

3. Проблема здесь, похоже, в ваших входных данных. Он пытается разделяться запятыми, но затем он помещает случайную запятую внутри поля. Можете ли вы исправить это, чтобы любые текстовые поля, которые могут содержать запятые, заключались в кавычки? Таким образом, вы можете использовать что-то вроде Text::CSV_XS для анализа данных.

4. Каждая часть скобок является заполнителем для того, что делается, поэтому часть, в которой нет скобки, — это значение, которое я ищу и хочу исключить, то есть лишняя запятая в имени. Там после этого будут расположены поля без запятой и поля с запятой после этого. Решение, которое я нашел, состояло в том, чтобы указать, сколько еще запятых осталось после этого, и скопировать поля без запятой и поля с запятой.

Ответ №1:

В итоге я обратился к старому коллеге, и это то, что он предложил, и это сработало. В моем файле у меня количество запятых равно 90 после имени, поэтому я указал, что этот шаблон повторяется 90 раз после этого.

   while(<IN>) {
        my $line = $_;
             $line =~ s/^(([^,]*,){13})([^,]*),*([^,]*)((,[^,]*){90})/1345/;
        print OUT "$line";
  }