Этот ответ основан на ответе Ральфа Реннквиста , но
Как и в ответе Ральфа, здесь предполагается, что заголовки отделяются от данных пробелом, а не двоеточием.
Для реализации цели №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 символов. Это также можно улучшить.
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"])
}
Если вы можете изменить данные, чтобы использовать только разделение пробелами (или только ":"), то следующая программа 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";
}
}