Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 按相同出现次数对列进行排序-使用awk、Sort、tr或uniq?_Unix_Sorting_Awk_Tr_Uniq - Fatal编程技术网

Unix 按相同出现次数对列进行排序-使用awk、Sort、tr或uniq?

Unix 按相同出现次数对列进行排序-使用awk、Sort、tr或uniq?,unix,sorting,awk,tr,uniq,Unix,Sorting,Awk,Tr,Uniq,假设我有一些选项卡分隔的数据: Peter 5 Joe 8 Peter 7 Peter 8 Joe 4 Laura 3 我想按照名字出现在第一列的次数(从最大到最小)对它进行排序 所以我们有彼得(3次)、乔(2次)和劳拉(1次) 它只需要按第一列排序,而不需要按第二列排序。我一直在阅读sort的文档,我认为它没有功能。有人有简单的方法吗?不性感,但适合你的例子: awk 'NR==FNR{a[$1]++;next}{ print a[$1],$0}' fil

假设我有一些选项卡分隔的数据:

Peter   5
Joe     8
Peter   7
Peter   8
Joe     4
Laura   3
我想按照名字出现在第一列的次数(从最大到最小)对它进行排序 所以我们有彼得(3次)、乔(2次)和劳拉(1次)


它只需要按第一列排序,而不需要按第二列排序。我一直在阅读sort的文档,我认为它没有功能。有人有简单的方法吗?

不性感,但适合你的例子:

 awk  'NR==FNR{a[$1]++;next}{ print a[$1],$0}' file file|sort -nr|sed -r 's/[0-9]* //'
使用您的数据进行测试:

kent$  cat n.txt
Peter   5
Joe     8
Peter   7
Peter   8
Joe     4
Laura   3

kent$  awk  'NR==FNR{a[$1]++;next}{ print a[$1],$0}' n.txt n.txt|sort -nr|sed -r 's/[0-9]* //'
Peter   8
Peter   7
Peter   5
Joe     8
Joe     4
Laura   3

不性感但适合你的例子:

 awk  'NR==FNR{a[$1]++;next}{ print a[$1],$0}' file file|sort -nr|sed -r 's/[0-9]* //'
使用您的数据进行测试:

kent$  cat n.txt
Peter   5
Joe     8
Peter   7
Peter   8
Joe     4
Laura   3

kent$  awk  'NR==FNR{a[$1]++;next}{ print a[$1],$0}' n.txt n.txt|sort -nr|sed -r 's/[0-9]* //'
Peter   8
Peter   7
Peter   5
Joe     8
Joe     4
Laura   3
这项工作:

for person in $(awk '{print $1}' file.txt | sort | uniq -c | sort -dnr | awk '{print $2}');
do grep -e "^$person[[:space:]]" file.txt;
done
这项工作:

for person in $(awk '{print $1}' file.txt | sort | uniq -c | sort -dnr | awk '{print $2}');
do grep -e "^$person[[:space:]]" file.txt;
done

这里有一种使用
GNU awk
的方法。运行方式如下:

awk -f script.awk file
script.awk的内容

BEGIN {
    FS="\t"
}

{
    c[$1]++
    r[$1] = (r[$1] ? r[$1] ORS : "") $0
}

END {

    for (i in c) {
        a[c[i],i] = i
    }

    n = asorti(a)

    for (i=1;i<=n;i++) {
        split(a[i], b, SUBSEP)
        x[++j] = b[2]
    }

    for (i=n;i>=1;i--) {
        print r[x[i]]
    }
}

这里有一种使用
GNU awk
的方法。运行方式如下:

awk -f script.awk file
script.awk的内容

BEGIN {
    FS="\t"
}

{
    c[$1]++
    r[$1] = (r[$1] ? r[$1] ORS : "") $0
}

END {

    for (i in c) {
        a[c[i],i] = i
    }

    n = asorti(a)

    for (i=1;i<=n;i++) {
        split(a[i], b, SUBSEP)
        x[++j] = b[2]
    }

    for (i=n;i>=1;i--) {
        print r[x[i]]
    }
}

这是一个非常难的排序标准。这段代码可以工作,但非常难看:

data=${1:-data}
awk '{ print $1 }' $data |
sort |
uniq -c |
sort -k2 |
join -1 2 -2 2 -o 1.1,2.1,2.2,2.3 - <(awk '{ print NR, $0 }' $data | sort -k2) |
sort -k1,1nr -k3,3 -k2n |
awk 'BEGIN{OFS="\t"} { print $3, $4 }'
使用带有内置排序的GNU
awk
,或者Perl或Python,可能比这更好

对于原始数据,输出为:

Peter   5
Peter   7
Peter   8
Joe     8
Joe     4
Laura   3
Peter   5
Peter   7
Peter   8
Peter   50
Peter   70
Peter   80
Peter   700
Peter   800
Peter   7002
Peter   8002
Peter   7000
Peter   8000
Peter   7001
Peter   8001
Joe     8
Joe     4
Joe     80
Joe     40
Laura   3
Laura   30
Laura   30
Pater   50
Pater   70
Pater   80
Jae     80
Jae     40
鉴于此数据的扩展版本:

Peter   5
Joe     8
Peter   7
Peter   8
Joe     4
Laura   3
Peter   50
Joe     80
Peter   70
Peter   80
Joe     40
Laura   30
Peter   700
Peter   800
Peter   7002
Peter   8002
Peter   7000
Peter   8000
Peter   7001
Peter   8001
Pater   50
Jae     80
Pater   70
Pater   80
Jae     40
Laura   30
输出为:

Peter   5
Peter   7
Peter   8
Joe     8
Joe     4
Laura   3
Peter   5
Peter   7
Peter   8
Peter   50
Peter   70
Peter   80
Peter   700
Peter   800
Peter   7002
Peter   8002
Peter   7000
Peter   8000
Peter   7001
Peter   8001
Joe     8
Joe     4
Joe     80
Joe     40
Laura   3
Laura   30
Laura   30
Pater   50
Pater   70
Pater   80
Jae     80
Jae     40

-k3,3
排序项对于该数据集是必需的;它在Pater的条目之前对Laura的条目进行排序(省略时,这两个列表交错排列)。

这是一个非常难的排序标准。这段代码可以工作,但非常难看:

data=${1:-data}
awk '{ print $1 }' $data |
sort |
uniq -c |
sort -k2 |
join -1 2 -2 2 -o 1.1,2.1,2.2,2.3 - <(awk '{ print NR, $0 }' $data | sort -k2) |
sort -k1,1nr -k3,3 -k2n |
awk 'BEGIN{OFS="\t"} { print $3, $4 }'
使用带有内置排序的GNU
awk
,或者Perl或Python,可能比这更好

对于原始数据,输出为:

Peter   5
Peter   7
Peter   8
Joe     8
Joe     4
Laura   3
Peter   5
Peter   7
Peter   8
Peter   50
Peter   70
Peter   80
Peter   700
Peter   800
Peter   7002
Peter   8002
Peter   7000
Peter   8000
Peter   7001
Peter   8001
Joe     8
Joe     4
Joe     80
Joe     40
Laura   3
Laura   30
Laura   30
Pater   50
Pater   70
Pater   80
Jae     80
Jae     40
鉴于此数据的扩展版本:

Peter   5
Joe     8
Peter   7
Peter   8
Joe     4
Laura   3
Peter   50
Joe     80
Peter   70
Peter   80
Joe     40
Laura   30
Peter   700
Peter   800
Peter   7002
Peter   8002
Peter   7000
Peter   8000
Peter   7001
Peter   8001
Pater   50
Jae     80
Pater   70
Pater   80
Jae     40
Laura   30
输出为:

Peter   5
Peter   7
Peter   8
Joe     8
Joe     4
Laura   3
Peter   5
Peter   7
Peter   8
Peter   50
Peter   70
Peter   80
Peter   700
Peter   800
Peter   7002
Peter   8002
Peter   7000
Peter   8000
Peter   7001
Peter   8001
Joe     8
Joe     4
Joe     80
Joe     40
Laura   3
Laura   30
Laura   30
Pater   50
Pater   70
Pater   80
Jae     80
Jae     40

-k3,3
排序项对于该数据集是必需的;它在Pater的条目之前对Laura的条目进行排序(省略时,这两个列表交错排列)。

下面是另一个使用awk的列表:

awk'{a[$1,++b[$1]]=$0;如果(b[$1]>max)max=b[$1]}

   END{ for(x=max;x>=1;x--)
         for( k in b )
           if( a[k,x] )
              for(y=1;y<=x;y++) {
                    print a[k,y]
                    delete a[k,y]
               }
   }' filename
END{for(x=max;x>=1;x--)
(b中的k)
if(a[k,x])

对于(y=1;y这里是另一个使用awk的:

awk'{a[$1,++b[$1]]=$0;如果(b[$1]>max)max=b[$1]}

   END{ for(x=max;x>=1;x--)
         for( k in b )
           if( a[k,x] )
              for(y=1;y<=x;y++) {
                    print a[k,y]
                    delete a[k,y]
               }
   }' filename
END{for(x=max;x>=1;x--)
(b中的k)
if(a[k,x])


对于(y=1;y这是否意味着第2列与这个问题无关?正确。该列中的数据只需与给定名称保持顺序。在结果集中,Peter的条目按第2列值的升序排列,而Joe的条目则按相反的顺序排列?JonathanLeffler:否-OP希望按降序排列第1列的出现,保持第2列在文件中出现的顺序。可能是重复出现的顺序(第1列)没关系,只要第二列保持给定名称的顺序。请参阅上面OP的评论。HTH。对于您对steve的解决方案的评论,在问题中提及文件大小会很有用。也许a数组中可以排序的数据量有一些限制?Match上的范围是多少s?最多3个?最多50个?什么?这是否意味着第2列与此问题无关?正确。该列中的数据只需与给定名称保持顺序。在结果集中,Peter的条目按第2列值的升序排列,而Joe的条目则按相反顺序排列?JonathanLeffler:不-OP不想这样做o在第一列出现时按降序排序,保持第二列在文件中出现的顺序。可能是重复出现的顺序(第一列)没关系,只要第二列保持给定名称的顺序。请参阅上面OP的评论。HTH。对于您对steve的解决方案的评论,在问题中提及文件大小会很有用。也许a数组中可以排序的数据量有一些限制?Match上的范围是多少s?三个最大值?50个最大值?什么?所以,为了简化示例数据,我没有提到$1中的名称偶尔会在$2中提及。这可以通过在$person之后添加a/t在代码中避免。您认为:grep“$person\|”会起作用吗?因此,为了简化示例数据,我没有提到$1中的名称偶尔会在示例数据中提及$2.通过在$person后面添加a/t,可以在代码中避免这种情况。您认为:grep'$person\|'有效吗?数据(字段2)根据问题下方的注释,需要保持有序。
-r
选项是不必要的;使用的正则表达式是基本的
sed
regex.@ChrisJ.Vargo是的,您可以删除'-r'选项。它也应该可以工作。哇。我刚刚在我的BSD框中运行了这个选项,它工作得非常出色。此外,在3800万行的列表中非常有效。Kent,非常感谢!@ChrisJ.Vargo很高兴为您提供帮助。它运行得很快,因为您有强大的CPU。:)我的代码中没有黑客算法数据(字段2)根据问题下方的注释,需要保持有序。
-r
选项是不必要的;使用的正则表达式是基本的
sed
regex.@ChrisJ.Vargo是的,您可以删除'-r'选项。它也应该可以工作。哇。我刚刚在我的BSD框中运行了这个选项,它工作得非常出色。此外,在3800万行的列表中非常有效。Kent,非常感谢!@ChrisJ.Vargo很高兴为您提供帮助。它运行得很快,因为您有强大的CPU。:)我的代码中没有黑客算法。史蒂夫,这是你在这么多天里回答我的第二个问题。你推荐什么资源来学习这样的脚本?仅供参考:我在一个大的文本文件上运行这个。我得到了以下错误:awk:调用未定义的函数asorti输入记录号码38823587,file input.txt源行号16@ChrisJ.Vargo:看起来我应该研究一下您之前的一些问题。从我所看到的情况来看,您使用的是
BSD/OSX awk
,不幸的是它不支持数组排序功能(
asort
asorti