Sorting AWK——如何进行选择性多列排序?

Sorting AWK——如何进行选择性多列排序?,sorting,awk,multiple-columns,Sorting,Awk,Multiple Columns,在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、

在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
的值),其中表的前一部分保持不变。

这可以通过以下步骤完成:


就我个人而言,我发现使用
awk
对列数组进行安全排序相当棘手,因为通常需要按住重复键进行排序。如果您需要有选择地对一组列进行排序,我将调用
paste
以获得一些帮助:

paste -d ' ' <(awk '{ print $1, $2, $3 }' file.txt) <(awk '{ print $4, $5, $6 | "sort -k 2" }' file.txt)
这可以在纯
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]$ 
[ghoti@pc~/tmp3]$cat文本
1安f 1 12伏
2B210W
3CH319X
4 d i 4 15 y
5 e j 5 11 z
[ghoti@pc~/tmp3]$cat doit.gawk
###要由asort()调用的函数。
功能cmp(i1、v1、i2、v2){
分割(v1,a1);分割(v2,a2);
如果(a1[2]>a2[2]){返回1;}

否则,如果(a1[2]您是指列
$4
$5
$6
?AWK从1:)您是对的。这是一个打字错误。感谢您的更正和解决方案!您是否有任何不调用外部函数的其他解决方案的想法?只是想知道这是否可能(但执行起来可能太复杂)
排序
粘贴
不是“外部功能”,而是基本的Unix工具。它们允许您构建非常灵活的解决方案。当原始文件的第5列的数字大于19且小于10时,这不起作用。我曾尝试仅使用
GNU awk
来执行此操作,但大约20分钟后我放弃了。我知道这不是强加的ble+1
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]$ 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]$