Транспонирование строк в столбцы при отсутствии нескольких строк с помощью AWK [дубликат]

-1
22.02.2016, 07:49
3 ответа

Этот ответ основан на ответе Ральфа Реннквиста , но

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

Как и в ответе Ральфа, здесь предполагается, что заголовки отделяются от данных пробелом, а не двоеточием.

Для реализации цели №1 требуется, чтобы ввод начинался со строфы, содержащей все заголовки (без сопроводительных данных) в желаемом порядке.

BEGIN { i = 0; j= 0; }
$1 != "" { if (i==0) C[++j] = $1; else { label = $1; $1 = ""; X[label,i] = $0; } next; }
{ i++; }
END {
    for ( k in C ) printf "  %8s\t", C[k];
    printf "\n";
    for ( j = 1; j <= i; j++ ) {
        for ( k in C ) printf "%8s\t", X[C[k],j];
        printf "\n";
    }
}

Обратите внимание, что i инициализируется значением 0 , и что случай i == 0 обрабатывается специально - {{1} } фиксируется только заголовок (поскольку это единственное, что должно быть там), и заголовки сохраняются в массиве C , индексируемом возрастающее целое число ( j ) , а не значение самого заголовка. В противном случае мы собираем данные. $ 1 = ""; стирает первое поле в строке и восстанавливает $ 0 как объединение всех остальных полей. (При этом теряется несколько пробелов между полями; это можно исправить, немного поработав.) Мы сохраняем значение $ 1 в ] label переменная , чтобы мы могли использовать ее в качестве индекса в массиве данных, X .

Так, например, этот ввод:

name
address
phone
height
weight

name John Lennon
phone 123
height 6' 1"
weight 180

name Sir Paul M.
address Liverpool
weight 175

name George
address 42                 Main St.
height 71"
weight 185 lbs

name Ringo Starr
address Penny Lane
phone 456 789

дает следующий результат:

      name         address           phone          height          weight
 John Lennon                         123           6' 1"             180
 Sir Paul M.     Liverpool                                           175
  George         42 Main St.                         71"         185 lbs
 Ringo Starr     Penny Lane      456 789

Столбцы будут отключены, если любое значение будет длиннее 15 символов. Это также можно улучшить.

0
28.01.2020, 05:11
awk -f  transpose_rows_to_cols.awk /tmp/1
title1  title2  title3  title4  title5
A1      A3  A4  A5
B1  B2          B5
C1  C2      C4  C5
D1  D2  D3      

PS. форматирование в терминале в порядке.

скрипт --

#!/usr/bin/awk -f
BEGIN {
    printf("title1\ttitle2\ttitle3\ttitle4\ttitle5\n");
    a["title1"] = a["title2"]= a["title3"]= a["title4"]= a["title5"] = ""
}
{
    if ($0 !~ /^$/) {
        if ($0 ~ /:/)  {FS=":"; $0=$0} else {FS=" "; $0=$0}
        a[$1]=$2
    } else {
        printf("%s\t%s\t%s\t%s\t%s\n", a["title1"], a["title2"], a["title3"], a["title4"], a["title5"])
        a["title1"] = a["title2"]= a["title3"]= a["title4"]= a["title5"] = ""
    }
}
END{
        printf("%s\t%s\t%s\t%s\t%s\n", a["title1"], a["title2"], a["title3"], a["title4"], a["title5"])
}
0
28.01.2020, 05:11

Если вы можете изменить данные, чтобы использовать только разделение пробелами (или только ":"), то следующая программа awk может это сделать. Возможно, вам придется подкорректировать ее для улучшения макета.

BEGIN { i = 1; }
$1 != "" { C[$1] = $1; X[$1,i] = $2 ; next; }
{ i++; }
END {
    asort(C);
    for ( k in C ) printf "  %8s\t", C[k];
    printf "\n";
    for ( j = 1; j <= i; j++ ) {
        for ( k in C ) printf "%8s\t",X[C[k],j];
        printf "\n";
    }
}
1
28.01.2020, 05:11

Теги

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