在AWK中按字段按数字排序

时间:2016-09-18 21:19:15

标签: awk

我有一个包含这些字符的文本文件,其中我的分隔符/分隔符为##@##

Steve##@##Jobs##@##Apple Inc.##@##32421213
Bill##@##Gates##@##Microsoft Corp.##@##234213
Steve##@##Wozniak##@##Apple Inc.##@##12343
Tim##@##Cook##@##Apple Inc.##@##323345223

现在我想让它们按数字排序&在第三场上升。我读过可以使用bash命令sort,遗憾的是它只支持单个字符作为分隔符。

最终,已排序的文件应该完全如下所示:

Steve##@##Wozniak##@##Apple Inc.##@##12343
Bill##@##Gates##@##Microsoft Corp.##@##234213
Steve##@##Jobs##@##Apple Inc.##@##32421213
Tim##@##Cook##@##Apple Inc.##@##323345223

是否有修复排序或我可以使用awk执行此操作吗?

3 个答案:

答案 0 :(得分:2)

这是一个(hackish)想法。使用awk将数字字段添加到每行的开头,以便我们可以使用sort对其进行排序,然后使用sed来删除我们在第一行中添加的内容步。这样的事情:

awk -vFS='##@##' '{print $4 "|" $0}' input | sort -n | sed -e 's/^[^|]*|//'

答案 1 :(得分:0)

使用perl的解决方案,无需其他命令

$ cat ip.txt 
Steve##@##Jobs##@##Apple Inc.##@##32421213
Bill##@##Gates##@##Microsoft Corp.##@##234213
abc##@##xyz##@##123 Corp.##@##234213
Steve##@##Wozniak##@##Apple Inc.##@##12343
Tim##@##Cook##@##Apple Inc.##@##323345223

$ perl -ne '($k)=/(\d+)$/; $h{$k} .= $_; END{foreach (sort {$a <=> $b} keys %h){print $h{$_}}}' ip.txt 
Steve##@##Wozniak##@##Apple Inc.##@##12343
Bill##@##Gates##@##Microsoft Corp.##@##234213
abc##@##xyz##@##123 Corp.##@##234213
Steve##@##Jobs##@##Apple Inc.##@##32421213
Tim##@##Cook##@##Apple Inc.##@##323345223
  • 行尾的数字用作键
  • 输入行基于键附加到哈希变量,这样也可以处理具有相同键的多行
  • 处理完所有行后,按键进行数字排序并打印出相应的值

答案 2 :(得分:0)

因为 sort (1)只接受单字符分隔符,所以您希望将分隔符字符串转换为排序识别的字符串,但不是数据中显示的值。您的最佳选择是无法出现在数据中:不可打印的字符。合理的候选者是ASCII字段分隔符,八进制034.当然,您必须在排序后恢复分隔符。

如果你使用bash,你可以通过八进制值直接访问字符,否则你的shell可能会有所不同。然后 sed 让它变得轻而易举:

$ s=$'\034'
$ sed "s/##@##/$s/g" dat | sort -t $s -k4 -n | sed "s/$s/##@##/g"

Steve##@##Wozniak##@##Apple Inc.##@##12343
Bill##@##Gates##@##Microsoft Corp.##@##234213
Steve##@##Jobs##@##Apple Inc.##@##32421213
Tim##@##Cook##@##Apple Inc.##@##323345223