如何在 awk 打印命令上使用排序?

Ano*_*ous 9 command-line awk text-processing

我正在编写的 awk 脚本中有几个命令:

print "Here are some players and their numbers, sorted by last name"
if(sum[x] > 500) {print x, $2}
Run Code Online (Sandbox Code Playgroud)

哪些输出:

Here are some players and their numbers, sorted by last name
Lebron James 23
Kevin Durant 35
Kobe Bryant 24
Blake Griffin 32
Dikembe Mutumbo 55
Run Code Online (Sandbox Code Playgroud)

如何使用awk 脚本中sort命令仅对玩家及其号码进行排序?

Way*_*Yux 12

您可以添加| sort -k2到您的命令中。这将根据第二列按字母顺序排序。

例子:

$ echo "Lebron James 23
Kevin Durant 35
Kobe Bryant 24
Blake Griffin 32
Dikembe Mutumbo 55" | sort -k2
Run Code Online (Sandbox Code Playgroud)

结果是

Kobe Bryant 24
Kevin Durant 35
Blake Griffin 32
Lebron James 23
Dikembe Mutumbo 55
Run Code Online (Sandbox Code Playgroud)

  • @KMoy:`if(sum[x] > 500) {print x, $2}` 是 Awk 代码,而 `| sort -k2` 是一个 shell 命令。显然,您不能将两者混为一谈,因为它们是不同的语言。相反,您需要将 `sort` 命令应用于运行您的 Awk 代码片段的 Awk 解释器的输出。如果您不知道我的意思,请扩展您的问题以向我们提供完整的图片。 (3认同)

ste*_*ver 9

尽管我不推荐它(考虑到通过外部sort命令管道结果的相对简单性),但您至少可以使用最新版本的 GNU awk(至少 4.0 IIRC)来执行此操作,如使用 gawk 对数组值和索引进行排序中所述

下面是如何实现它,假设您在索引为 的关联数组中拥有数据Firstname Lastname。首先,您需要定义一个自定义比较函数来拆分索引,首先比较Lastname然后(作为决胜局)Firstname例如

function mycmp(ia, va, ib, vb, sa, sb) {
  if(split(toupper(ia), sa) && split(toupper(ib), sb)) {
    if(sa[2] < sb[2]) return -1;
    else if (sa[2] > sb[2]) return 1;
    else {
      # compare first names
      if(sa[1] < sb[1]) return -1;
      else if (sa[1] > sb[1]) return 1;
      else return 0;
    }
  }
  else return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在您可以使用PROCINFO["sorted_in"]@zwets 评论中提到的数组排序方法

PROCINFO["sorted_in"] = "mycmp";
for(i in a) print i, a[i];
Run Code Online (Sandbox Code Playgroud)

把它放在一起

#!/usr/bin/gawk -f

function mycmp(ia, va, ib, vb, sa, sb) {
  if(split(toupper(ia), sa) && split(toupper(ib), sb)) {
    if(sa[2] < sb[2]) return -1;
    else if (sa[2] > sb[2]) return 1;
    else {
      # compare first names
      if(sa[1] < sb[1]) return -1;
      else if (sa[1] > sb[1]) return 1;
      else return 0;
    }
  }
  else return 0;
}

{
  a[$1" "$2] = $3;
}

END {
  PROCINFO["sorted_in"] = "mycmp";
  for(i in a) print i, a[i];
}
Run Code Online (Sandbox Code Playgroud)

测试:

$ ./namesort.awk yourfile
Kobe Bryant 24
Kevin Durant 35
Blake Griffin 32
Lebron James 23
Dikembe Mutumbo 55
Run Code Online (Sandbox Code Playgroud)

在较小或较旧版本的 awk 中,最好的办法可能是存储索引为 by 的数据Lastname Firstname,使用传统的排序asorti,然后在遍历数组以打印它时拆分和交换索引的字段:

awk '
  {a[$2" "$1]=$3} 
  END {
    n=asorti(a,b); for (i=1;i<=n;i++) {split(b[i],s); print s[2], s[1], a[b[i]]}
}' yourfile
Run Code Online (Sandbox Code Playgroud)


hee*_*ayl 5

为了sort只由空格隔开的第二场,使用关键-k2,2

... | sort -k2,2
Run Code Online (Sandbox Code Playgroud)

默认情况下sort按字典顺序进行排序。

请注意,如果您没有提及排序键的最后一个字段,即如果您只是使用,-k2那么您可能无法获得所需的结果,因为这将sort根据从第二个开始的所有字段

还要检查man sort