2016-09-18 50 views
0

数字线由我场有包含这些字符,在我的分隔符/分隔符是##@##一个文本文件:排序在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?

回答

2

这里有一个(黑客)的想法。使用awk将数字字段添加到每行的开头,以便我们可以用sort对其进行分类,然后使用sed来摆脱我们在第一步中添加的内容。类似的东西:

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

这是标准的方法,但是使用'\ t'代替'|'作为分隔符,因为这是默认的'sort'分隔符,这样你就可以告诉排序只使用第一个字段(因为YMMV的顺序是'|'vs其他字符),所以你可以在之后使用它的默认分隔符:'awk -F'## @ ##'-v OFS ='\ t''{print $ 4,$ 0}'输入| sort -k1,1n |切-f2-'。 –

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 
  • 在线的端部的数量被用作一个关键
  • 输入线的追加到哈希可变基于密钥,也可以处理多个具有相同密钥的行
  • 处理所有行后,密钥将按数字排序,并且相应的值将打印d出
0

因为排序(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