我有一个文本文件,其中包含以下内容:
标题1 A1
标题3 A3
标题4 A4
标题5 A5
标题1 B1
标题2 B2
标题5 B5
标题1 C1
标题2 C2
标题4 C4
标题5 C5
标题1 D1
标题2 D2
标题3 D3
我想要如下的输出:
title1 title2 title3 title4 title5
A1 A3 A4 A5
B1 B2 B5
C1 C2 C4 C5
D1 D2 D3
您能告诉我如何使用 AWK 编写一段代码吗?
提前致谢!
答案1
如果您可以将数据更改为仅使用空格分隔(或仅使用“:”),则以下 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";
}
}
答案2
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
附言。在终端上格式化就可以了。
脚本 -
#!/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"])
}
答案3
这个答案建立在拉尔夫·伦奎斯特的回答, 但
- 假设列应按用户指定的顺序输出,而不是按标题的字母顺序输出,并且
- 允许数据值是多字。
就像拉尔夫的回答一样,这假设标题与数据之间用空格而不是冒号分隔。
为了实现目标#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
情况经过特殊处理 - 仅捕获标题(因为这是唯一应该存在的东西),并且标题存储在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 个字符或更长,则这些列将关闭。这一点还可以改进。