извлекать необязательные значения полей из строк - PullRequest
3 голосов
/ 13 января 2012

У меня есть текст в виде отдельных строк, где каждая строка имеет CSV-подобный формат:

SOME BUNCH OF TEXT, FIELD_A: 12, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656

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

SOME BUNCH OF TEXT, FIELD_A: 12, NOT_INTERESTED: 235, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656, FIELDS

В результате обработки этого текста я хочу получить чистый CSV-файл, в котором мои поля указываются один за другим:

12,0.2321,12:10:08 2011/07/22,656

Если какое-то поле отсутствует, то я бы хотел просто пропустить значение (например, FIELD_B отсутствовало):

12,,12:10:08 2011/07/22,656

Как я могу сделать это с помощью таких команд, как sed, perl или awk? Я попытался извлечь отдельное поле с помощью perl -pe 's/^.*?(FIELD_A: (.*?),)?.*?$/\2/' и потерпел неудачу - регулярное выражение просто игнорирует мое поле, даже если оно отображает

Ответы [ 2 ]

2 голосов
/ 13 января 2012

Вы можете использовать awk с ассоциативным массивом, как показано ниже.Зациклите поля и разделите их на :.Затем сохраните пару ключ-значение в ассоциативный массив.Наконец распечатайте нужные поля.

awk -F, '{
 split("",arr)
 for(i=1; i<=NF; i++){
   a=index($i, ":")
   if(a != 0){
     # split on first colon to get key-value pair
     key=substr($i,1,a-1)
     val=substr($i,a+1)

     # remove leading spaces from key and value
     gsub(/^ */,"",key)
     gsub(/^ */,"",val)

     # store in an associative array
     arr[key]=val
   }   
 }
 # print out the desired fields
 print arr["FIELD_A"]","arr["FIELD_B"]","arr["FIELD_C"]","arr["FIELD_D"]
}' data.txt
1 голос
/ 13 января 2012

Как насчет этого (при условии, что имена файлов известны):

#!/usr/bin/perl
use strict;
use warnings;

my @f = qw(FIELD_A FIELD_B FIELD_C FIELD_D);
while(my $line = <DATA>) {
    chomp $line;
    my @r;
    for(@f) {
        if ($line =~ /$_:\s*([^,]+)/) {
            push @r, $1;
        } else {
            push @r,'';
        }
    }
    print join(',',@r), "\n";
}
__DATA__
SOME BUNCH OF TEXT, FIELD_A: 12, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656
SOME BUNCH OF TEXT, FIELD_A: 12, NOT_INTERESTED: 235, FIELD_B: 0.2321, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656, FIELDS
SOME BUNCH OF TEXT, FIELD_A: 12, NOT_INTERESTED: 235, FIELD_C: 12:10:08 2011/07/22, FIELD_D: 656, FIELDS

выход:

12,0.2321,12:10:08 2011/07/22,656
12,0.2321,12:10:08 2011/07/22,656
12,,12:10:08 2011/07/22,656
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...