4

在 awk 中,我该怎么做:

输入:

1  a  f  1  12  v  
2  b  g  2  10  w  
3  c  h  3  19  x  
4  d  i  4  15  y  
5  e  j  5  11  z  

所需的输出,通过在 处对数值进行排序$5

1  a  f  2  10  w  
2  b  g  5  11  z  
3  c  h  1  12  v  
4  d  i  4  15  y  
5  e  j  3  19  x  

请注意,排序应该影响$4$5$6(基于 的值$5),其中表的前一部分保持不变。

4

3 回答 3

5

这可以在多个步骤的帮助下完成paste

$ gawk '{print $1, $2, $3}' in.txt > a.txt
$ gawk '{print $4, $5, $6}' in.txt | sort -k 2 -n b.txt > b.txt
$ paste -d' ' a.txt b.txt
1 a f 2 10 w
2 b g 5 11 z
3 c h 1 12 v
4 d i 4 15 y
5 e j 3 19 x
于 2012-10-01T17:51:34.313 回答
4

就个人而言,我发现使用awk安全地对列数组进行排序相当棘手,因为您通常需要保存和排序重复的键。如果您需要有选择地对一组列进行排序,我会paste寻求一些帮助:

paste -d ' ' <(awk '{ print $1, $2, $3 }' file.txt) <(awk '{ print $4, $5, $6 | "sort -k 2" }' file.txt)

结果:

1 a f 2 10 w
2 b g 5 11 z
3 c h 1 12 v
4 d i 4 15 y
5 e j 3 19 x
于 2012-10-02T01:07:46.493 回答
4

可以在 pure 中完成awk,但正如@steve 所说,这并不理想。 gawk排序功能有限,awk根本没有内置排序。也就是说,这是一个使用比较函数的(相当骇人听闻的)解决方案gawk

[ghoti@pc ~/tmp3]$ cat text 
1  a  f  1  12  v  
2  b  g  2  10  w  
3  c  h  3  19  x  
4  d  i  4  15  y  
5  e  j  5  11  z  
[ghoti@pc ~/tmp3]$ cat doit.gawk 
### Function to be called by asort().
function cmp(i1,v1,i2,v2) {
  split(v1,a1); split(v2,a2);
  if (a1[2]>a2[2])      { return 1; }
  else if (a1[2]<a2[2]) { return -1; }
  else                  { return 0; }
}

### Left-hand-side and right-hand-side, are sorted differently.
{
  lhs[NR]=sprintf("%s %s %s",$1,$2,$3);
  rhs[NR]=sprintf("%s %s %s",$4,$5,$6);
}

END {
  asort(rhs,sorted,"cmp");    ### This calls the function we defined, above.
  for (i=1;i<=NR;i++) {       ### Step through the arrays and reassemble.
    printf("%s %s\n",lhs[i],sorted[i]);
  }
}    
[ghoti@pc ~/tmp3]$ gawk -f doit.gawk text 
1 a f 2 10 w
2 b g 5 11 z
3 c h 1 12 v
4 d i 4 15 y
5 e j 3 19 x
[ghoti@pc ~/tmp3]$ 

这会将整个输入文件保存在数组中,以便在排序后重新组合行。如果您的输入是数百万行,这可能会有问题。

请注意,您可能希望使用printfandsprintf函数来设置适当的输出字段分隔符。

asort()您可以在 gawk 手册页中找到有关使用 with 函数的文档;寻找PROCINFO["sorted_in"]

于 2012-10-03T14:06:01.527 回答