Объединить столбцы в файле на основе заголовка столбца

Аналогично:https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=768949

Мне удалось исправить неисправное обновление, выполнив

sudo systemctl disable avahi-daemon
sudo apt upgrade
sudo systemctl enable avahi-daemon

2
14.04.2020, 10:25
3 ответа

Если ввод осуществляется с помощью табуляции -, разделенной:

awk -F"\t" '
NR == 1 {for (i=1; i<=NF; i++)  COL[i] = $i
        }
        {for (i=1; i<=NF; i++) OUT[NR, COL[i]] = $i
        }
END     {for (n=1; n<=NR; n++)  {split ("", DUP)
                                 for (i=1; i<=NF; i++)  if (!DUP[COL[i]]++) printf "%s" FS, OUT[n,COL[i]]
                                 printf RS
                                }
        }
' file
A   B   C   
1   5   4   
3   1   2   
2   2   1   
1       3   
3       2   
1       4   

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

Обработка дубликатов может стать серьезной проблемой для более сложных файловых структур.

2
28.04.2021, 23:18

Несколько иной подход, не требующий «буферизации» всего файла:

AWK-скриптcolmerge.awk:

FNR==1{
    for (i=1; i<=NF; i++)
    {
    hdr[i]=$i;
    if (map[$i]==0) {map[$i]=i; uniq_hdr[++u]=$i; printf("%s",$i);}
    if (i==NF) printf("%s",ORS); else printf("%s",OFS);
    }
}

FNR>1{
    delete linemap;
    for (i=1; i<=NF; i++) if ($i!="") linemap[hdr[i]]=$i;
    for (i=1; i<=u; i++)
    {
    printf("%s",linemap[uniq_hdr[i]]);
    if (i==u) printf("%s",ORS); else printf("%s",OFS);
    }
}

Использовать как

awk -F'\t' -v OFS='\t' -f colmerge.awk file

При этом будут собраны все заголовки и определены "уникальные" заголовки и их первое появление в строке 1, а для каждой последующей строки будет создана карта между заголовками и непустыми -значениями, которая затем распечатывается в порядке «уникальные» заголовки, определенные при обработке первой строки.

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

Также обратите внимание, что оператор deleteдля всего массива linemapможет поддерживаться не всеми awkреализациями (должен работать на gawk, mawkи nawk, однако ).

1
28.04.2021, 23:18

для отдельной вкладки -.

прочитать заголовок и соответствующие номера столбцов (s )в массив, где они появились во входном файле; затем разбивая входной файл в каждом столбце на одно и то же имя файла headerName.txt, имеющее такое же имя заголовка. в конце концов соедините их вместе и используйте командуcolumnдля украшения вывода.

awk -F'\t' '
    ## find all the column number(s) when same header found and store in `h` array
    ## key is the column number and value is header name. for an example:
    ## for the header value 'A', keys will be columns 1 &4
    NR==1{ while (++i<=NF) h[i]=$i; next; }

         { for (i=1; i<=NF; i++) {

    ## save the field content to a file which its key column matches with the column 
    ## number of the current field. for an example:
    ## for the first field in column 1; the column number is 1, and so 1 is the key  
    ## column for header value A, so this will be written to "A.txt" filename
    ## only if it was not empty.
               if ($i!=""){ print $i> h[i]".txt" };
         }; }

    ## at the end paste those all files and beautify output with `column` command.
    ## number of.txt files above is limit to the number of uniq headers in your input. 
END{ system("paste *.txt |column \011 -tn") }' infile

комментарии -свободная команда:

awk -F'\t' '
    NR==1{ while (++i<=NF) h[i]=$i; next; }
         { for (i=1; i<=NF; i++) {
               if ($i!=""){ print $i> h[i]".txt" };
         }; }
END{ system("paste *.txt |column \011 -tn") }' infile
1
28.04.2021, 23:18

Теги

Похожие вопросы