我有这种格式的数据(很多这样的行):
TASK : Task 1
TASK : Task 2
TASK : Task 3
OWNER : Emp 1
OWNER : Emp 2
OWNER : Emp 3
Deadline : Monday
Deadline : Tuesday
Deadline : Wednesday
这个,我想转换为:
TASK OWNER Deadline
Task 1 Emp 1 Monday
Task 2 Emp 2 Tuesday
Task 3 Emp 3 Wednesday
即使我可以在没有列标题名称的情况下提取每个列,它也会很好。之后我可以手动添加列名。
有没有办法使用'awk'或'sed'?
答案 0 :(得分:5)
使用awk的一种方式:
awk -F': *' '{i=NR%3;i=i?i:3;a[i]=a[i]?a[i]"\t"$2:$2}
END{for(x=1;x<=length(a);x++)print a[x]}' file
它保留了订单,省略了标题行:
kent$ cat f
TASK : Task 1
TASK : Task 2
TASK : Task 3
OWNER : Emp 1
OWNER : Emp 2
OWNER : Emp 3
Deadline : Monday
Deadline : Tuesday
Deadline : Wednesday
kent$ awk -F': *' '{i=NR%3;i=i?i:3;a[i]=a[i]?a[i]"\t"$2:$2}END{for(x=1;x<=length(a);x++)print a[x]}' f
Task 1 Emp 1 Monday
Task 2 Emp 2 Tuesday
Task 3 Emp 3 Wednesday
awk -F': *' #":any <space>" as FS
'{i=NR%3;i=i?i:3; #take NR%3 in i, if i=0, set i=3. because
#we want the i=0 case at the end of the output
a[i]=a[i]?a[i]"\t"$2:$2}#concatenate the 2nd column to an array
END{for and print}' file#print the content of the array at the end
我们可以将标题保存在var h
中并在通过a (array)
之前将其打印出来:
awk -F': *' '{...h=i==1?(h?h"\t"$1:$1):h;a[i]=..}
END{print h;for...}' file
答案 1 :(得分:2)
这是一个相对不错的awk
版本:
BEGIN {FS=" : ";OFS="\t"}
/^TASK/ {task [tpos++] = $2}
/^OWNER/ {owner[opos++] = $2}
/^Deadline/ {due [dpos++] = $2}
END {
print "TASK", "OWNER", "DEADLINE"
for (i in task) {
print task[i],owner[i],due[i]
}
}
:)
它为每个块保存一行,因为它不需要gsub()
调用,因为它使用:
作为分隔符。将其存储在test.awk
中,然后按如下方式执行:
awk -f test.awk input.txt
<强>更新强>:
上面的命令导致shell中的未对齐输出:
TASK OWNER DEADLINE
Task 1 Emp 1 Monday
Task 2 Emp 2 Tuesday
Task 3 Emp 3 Wednesday
您可以使用column
命令解决此问题:
awk -f test.awk input.txt | column -t -s $'\t'
现在输出看起来很干净:
TASK OWNER DEADLINE
Task 1 Emp 1 Monday
Task 2 Emp 2 Tuesday
Task 3 Emp 3 Wednesday
答案 2 :(得分:2)
Perl解决方案:
perl -le 'while (<>) {
chomp;
($h, $t) = split / : /;
$i++, push @{$ar[0]}, $h if $h ne $ar[0][-1];
push @{$ar[$i]}, $t;
};
$" = "\t";
print "@{$ar[0]}";
print join $", map shift @{$ar[$_]}, 1 .. $#ar while @{$ar[1]}'
如果标签没有很好地对齐文字,我会使用Text::Table。