Как транспонировать или сводить данные текстового файла в Unix? - PullRequest
0 голосов
/ 25 июня 2019

У меня есть входной текстовый файл в Unix с данными такого типа.

Event_date:20190512044638
Error_code:5858
Event_type:GPRS data
Duration:772
Missing_provider_id:46009

Event_date:20190512044638
Error_code:780678

Event_date:20190512064535
Error_code:5858
Event_type:GPRS data
Duration:2172
Missing_provider_id:722310

Я хочу, чтобы эти данные были в следующем формате вывода:

Event_date      Error_code  Event_type  Duration  Missing_provider_id
20190512044638  5858        GPRS data   772       46009
20190512044638  780678      
20190512064535  5858        GPRS data   2172      722310

Я попробовал комбинациюкоманд awk и sed, но не получилось.Как я могу получить этот вывод?

Event_date:20190512044638
Error_code:5858
Event_type:GPRS data
Duration:772
Missing_provider_id:46009

Event_date:20190512044638
Error_code:780678

Event_date:20190512064535
Error_code:5858
Event_type:GPRS data
Duration:2172
Missing_provider_id:722310

я хочу, чтобы эти данные были в следующем формате вывода:

Event_date      Error_code  Event_type  Duration  Missing_provider_id
20190512044638  5858        GPRS data   772       46009
20190512044638  780678      
20190512064535  5858        GPRS data   2172      722310

Ответы [ 3 ]

1 голос
/ 25 июня 2019

Использование GNU awk и 2D-массивов:

awk '
BEGIN {                         
    r=2                                           # data records in a start from 2
    FS=":"                                        # split at :
    OFS="\t"                                      # tab separated fields
    a[0][0]                                       # initialize a array
}
$0!="" {                                          # for nonempty records
    if(!($1 in a[0])) {                           # add keys to headers when needed
        a[0][$1]=++f                              # for lookups
        a[1][f]=$1                                # for printing
    }
    a[r][a[0][$1]]=$2                             # store value
    next
}
{                                                 # empty record -> new array record
    r++
}
END {                                             # after records are processed
    # delete a[0][0]                              # 
    for(i=1;i<=r;i++)                             # iterate records
        for(j=1;j<=f;j++)                         # iterate fields
            printf "%s%s",a[i][j],(j==f?ORS:OFS)  # output
}
' file | column -t -s $'\t'                       # column used for pretty-print

Вывод:

Event_date      Error_code  Event_type  Duration  Missing_provider_id
20190512044638  5858        GPRS data   772       46009
20190512044638  780678
20190512064535  5858        GPRS data   2172      722310
0 голосов
/ 26 июня 2019

вот еще один

awk -F: -v RS= 'BEGIN   {OFS=FS}
                NR==FNR {for(i=1;i<NF;i+=2)
                           if(!($i in h)) {h[$i]; ho[++c]=$i}; 
                         next}
                FNR==1  {for(i=1;i<=c;i++) printf "%s",ho[i] (i==c?ORS:OFS)}
                        {delete v;
                         for(i=1;i<NF;i+=2) v[$i]=$(i+1);
                         for(i=1;i<=c;i++) printf "%s", v[ho[i]] (i==c?ORS:OFS)}' file{,} | 
column -ts:

Event_date      Error_code  Event_type  Duration  Missing_provider_id
20190512044638  5858        GPRS data   772       46009
20190512044638  780678
20190512064535  5858        GPRS data   2172      722310

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

0 голосов
/ 25 июня 2019

Это awk может сделать: (поля, разделенные табуляцией)

PS это не удастся, если поле отсутствует, все должны быть в порядке.

awk -F: 'NR==1 {print $1,$3,$5,$7,$9} {print $2,$4,$6,$8,$10}'  RS= ORS='\n' OFS='\t' file
Event_date      Error_code      Event_type      Duration        Missing_provider_id
20190512044638  5858    GPRS data       772     46009
20190512044638  780678
20190512064535  5858    GPRS data       2172    722310

Более общее решение:

awk -F: 'NR==1 {print $1,$3,$5,$7,$9} {for(i=2;i<=NF;i+=2) printf "%s\t",$i;print ""}'  RS= ORS='\n' OFS='\t' file
Event_date      Error_code      Event_type      Duration        Missing_provider_id
20190512044638  5858    GPRS data       772     46009
20190512044638  780678
20190512064535  5858    GPRS data       2172    722310

NR==1 {print $1,$3,$5,$7,$9} может быть установлен на некоторый статический заголовок, такой как NR==1 {print "F1","F2","F3","F4","F5"} etc

...