2017-02-28 82 views
2

我试着去排序的特定字段这个文件,我想要做的这一切在awk我的awk命令排序,却意外地省略重复

"firstName": "gdrgo", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "lastName": "222",dfg 
"xxxxx": "John", "firstName": "beto", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "lastName": "111","xxxxx": "John", 
"xxxxx": "John", "firstName": "beto", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "lastName": "111","xxxxx": "John", 
"xxxxx": "John", "xxxxx": "John", "firstName": "beto2", "xxxxx": "John","lastName": "555", "xxxxx": "John","xxxxx": "John", 
"xxxxx": "John", "xxxxx": "John", "firstName": "beto2", "xxxxx": "John","lastName": "444", "xxxxx": "John","xxxxx": "John", 
"firstName": "gdrgo", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "xxxxx": "John", "lastName": "222",dfg 
"xxxxx": "John", "xxxxx": "John", "firstName": "beto2", "xxxxx": "John","lastName": "444", "xxxxx": "John","xxxxx": "John", 

我使用这个命令:

awk -F'.*"firstName": "|",.*"lastName": "|",' '{b[$3]=$0} END{for(i in b){print i}}' sumacomando 

,其输出:

111 
222 
444 
555 

但我预期:

111 
111 
222 
222 
444 
444  
555 

也就是说,尽管实际输出按照需要进行了表面排序,但却意外丢失了重复值。

回答

2
  • 排序/指数在awk的阵列中,总是联想数组(d字典),是一个实现细节 - 不保证特定的顺序;在你的情况下,输出只是恰巧是排序。

  • 独特,所以如果$3超过1个输入行具有相同的值,则b[$3]=...分配相互覆盖 - 最后一胜。

您因此:

  • 必须使用顺序索引阵列来存储你的第三个字段值($3

  • 已经通过自己的价值观所产生的阵列排序。

%的POSIX awk中规范,awk有没有内置排序功能,但GNUawk呢,让下面的解决方案,其asort()功能:

awk -F'.*"firstName": "|",.*"lastName": "|",' ' 
    { b[++n]=$3 } END{ asort(b); for(i=1;i<=n;++i) print b[i] } 
' sumacomando 

注意,这并未”包括存储相关的完整行($0)。


如果你也想存储相关的实线,而在(GNU)awk中依然表现排序,它变得更加复杂:

awk -F'.*"firstName": "|",.*"lastName": "|",' ' 
    # Use a compound key to store the value of $3 plus a sequential index 
    # to disambiguate, and store the input row ($0) as the value. 
    { vals[$3,++n]=$0 } 
    END{  
    # Sort by compound key using the helper function defined below. 
    asorti(vals, names, "cmp_func"); 
    # Output the first half of the compound key, i.e., the value of $3, 
    # followed by the associated input row. 
    for(i=1;i<=n;++i) print gensub(SUBSEP ".*$", "", 1, names[i]), vals[names[i]] 
    } 
    # Helper sort function that splits the compound key into its components 
    # - $3 value and sequential index - and compares the $3 values alphabetically 
    # and the indices numerically. 
    function cmp_func(i1, v1, i2, v2) { 
    split(i1, tokens1, SUBSEP) 
    split(i2, tokens2, SUBSEP) 
    if (tokens1[1] < tokens2[1]) return -1 
    if (tokens1[1] > tokens2[1]) return 1 
    i1 = int(tokens1[2]) 
    i2 = int(tokens2[2]) 
    if (i1 < i2) return -1 
    if (i1 > i2) return 1 
    return 0 
    } 
' sumacomando 

管道到sort作为一种替代解决方案大大简化了事务:

awk -F'.*"firstName": "|",.*"lastName": "|",' '{ print $3, $0 }' sumacomando | sort -k1,1 

但是,请注意,纯Awk解决方案以上保留了重复的$3值之间的输入顺序,其中sort-assisted解决方案没有。

相反,纯粹的Awk解决方案需要将所有输入一次存储在内存中,而sort实用程序经过优化,可以处理大型输入集并按需使用临时文件。

+0

嗨对不起 – victorhernandezzero

2

你的领域分离的选择是非常规的,也许更好的使用这个代替

awk -F'[:,]' '{for(i=1;i<=NF;i++) 
        if($i~"\"lastName\"") 
         {gsub(/"/,"",$(i+1)); 
         print $(i+1)}}' file | sort 

如果您awkasort功能,你可以做钥匙的这个代替

awk -F'[:,]' '{for(i=1;i<=NF;i++) 
       if($i~"\"lastName\"") 
        {gsub(/"/,"",$(i+1)); 
        a[++c]=$(i+1)}} 
      END {asort(a); 
       for(k=1;k in a;k++) print a[k]}' file 
+0

很好的答案非常感谢你,但我看起来像完全用awk完成不同的原因;但如果我没有找到其他答案,我会选择你作为最佳答案 – victorhernandezzero

+0

awk has asort? – victorhernandezzero

+0

'gawk'有,它不是“古典”'awk'的一部分,因为对原始的unix工具哲学 – karakfa

1

@victorhernandezzero:@try:我尝试了一种不同的方法,我希望它可以帮助你/全部。只有一个awk(没有其他命令)。

awk '/lastName/{getline;while(!$0){getline};A[$0]} END{num=asorti(A, B);for(i=1;i<=num;i++){print B[i]}}' RS='[: ",]' Input_file 

EDIT1:上述方案不会给你所需要的重复,特别感谢mklement0让我知道,下面可以帮助你在相同的了。

awk '/lastName/{getline;while(!$0){getline};A[++j]=$0} END{num=asort(A, B);for(i=1;i<=num;i++){print B[i]}}' RS='[: ",\n]' Input_file 
+2

我感谢您的意愿,以改善您的问题。 您的答案的排序部分现在与我的答案中的第一个解决方案相同(除非您复制数组,这不是必需的)。 值提取部分不需要重写 - OP的命令在这方面工作良好 - 并且您的重写是复杂的,涉及到getline,这很少是正确的工具。这也使得解决方案难以推广。 P.S .:请不要在你的回答中提到OP。无论如何,OP都会收到答案通知,这对未来的读者来说是一种分心。 – mklement0

+0

嗨,对不起,这是一个混淆,这个命令的工作原理是因为安装gawk,但不适用本地与nawk或awk对所有人抱歉 – victorhernandezzero