我有这个简化的数字表,由2列和几行组成。这里的要点是每列,取值并按行排序,以便每行有4个值。这个file.txt:
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
这就是我想要的结果:
1 1 1 1
1 1 1 1
1
2 2 2 2
2 2 2 2
2
我执行以下操作,为了清楚起见创建了script.awk。
awk -f script.awk file.txt
其中script.awk是
{for (i=1;i<=NF;i++)
printf "%s" (NR %4==0 ? RS:FS), $i;}
但它没有炒作。我知道以下命令适用于一列,但我不明白为什么它不适用于每列中的循环。
{printf "%s" (NR %4==0 ? RS:FS), $1;}
如果不可能,我想解释所使用的sommands,因为我是这种语言的新手。谢谢!
答案 0 :(得分:3)
我会发布一个通用解决方案:
awk '{for (i=1;i<=NF;i++) a[i,NR]=$i; }END{
for(i=1;i<=NF;i++) {
for(j=1;j<=NR;j++)
printf "%s%s", a[i,j],(j%4==0||j==NR?"\n":" ");
}
}' file
这适用于输入文件中的动态列,例如:
kent$ cat f
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
kent$ awk '{for (i=1;i<=NF;i++) a[i,NR]=$i; }END{
for(i=1;i<=NF;i++) {
for(j=1;j<=NR;j++)
printf "%s%s", a[i,j],(j%4==0||j==NR?"\n":" ");
}
}' f
1 1 1 1
1 1 1 1
1
2 2 2 2
2 2 2 2
2
3 3 3 3
3 3 3 3
3
4 4 4 4
4 4 4 4
4
您只需更改4
即可控制输出中的cols数量。它也很容易作为awk -v cols="$var" ...
答案 1 :(得分:2)
使用awk
即可:
awk '{a[$1]++; b[$2]++} END{for (i=1; i<=a[$1]; i++) printf "%s%s", $1, (i%4)?FS:ORS ;
print ""; for (i=1; i<[$2]; i++) printf "%s%s", $2, (i%4)?FS:ORS; print ""}' file
1 1 1 1
1 1 1 1
1
2 2 2 2
2 2 2 2
2
答案 2 :(得分:2)
另一种方法,使用awk
和sort
:
cat file|awk '{printf("%s\n%s\n",$1,$2)}'|sort|awk 'BEGIN{ORS=" "}
{if(NR==1){l=$1};if($1!=l){printf("\n");NR=1};
print $1;if(NR%4==0){printf("\n")};l=$1}'
1 1 1 1
1 1 1 1
1
2 2 2 2
2 2 2 2
2
答案 3 :(得分:1)
你的方法的问题是awk一次遍历每一行(记录),所以你的块中的循环将应用第一行中的第一个字段,第二个字段,然后移到下一行。这不能做你想做的事情,因为你需要先做第一个字段的所有元素才能做任何事情。
一个选项是构建两个字段的数组,然后在到达文件末尾时打印它们:
awk 'function p(a) { s=""; for(i=1;i<=NR;++i) s=s a[i] (i%4==0 ? RS:FS); print s }
{ a[NR]=$1; b[NR]=$2 }
END { p(a); p(b) }' file