2017-10-07 98 views
-1

我想根据出场次数对输入进行排序。但是,我不想删除唯一或非唯一的行。举例来说,如果我得到以下输入:如何根据出现的UNIX数量对行进行排序?

Not unique 
This line is unique 
Not unique 
Also not unique 
Also unique 
Also not unique 
Not unique 

我会找一组流水线的命令,可输出以下会:

This line is unique 
Also unique 
Also not unique 
Also not unique 
Not unique 
Not unique 
Not unique 

感谢您的帮助,您可以提供,我一直在尝试使用不同的独特和排序组合,但无法弄清楚,解决方案最好是单线程。

更新:谢谢所有回复的人,尤其是@batMan,他的回答正是我用我熟悉的命令寻找的。

我仍在试图学习如何管道和使用多个命令看似简单的任务,所以我可能适应他的答案与2列工作?例如,如果原始输入过:

Notunique dog 
Thislineisunique cat 
Notunique parrot 
Alsonotunique monkey 
Alsounique zebra 
Alsonotunique beaver 
Notunique dragon 

而且我想要的输出进行排序的第一列像这样:

Thislineisunique cat 
Alsounique zebra 
Alsonotunique monkey 
Alsonotunique beaver 
Notunique dog 
Notunique parrot 
Notunique dragon 

谢谢大家的是提前这么有用!

+0

你能证明你有什么尝试到目前为止?我会使用一个简短的Python脚本,使用'collections.Counter'可以非常简短,但这对纯粹的'shell'解决方案不起作用。 – norok2

回答

0

uniq + sort + grep溶液:

扩展inputfile内容:

Not unique 
This line is unique 
Not unique 
Also not unique 
Also unique 
Also not unique 
Not unique 
Also not unique 
Also not unique 

排序初始文件事先:

sort inputfile > /tmp/sorted 

uniq -u /tmp/sorted; uniq -dc /tmp/sorted | sort -n | cut -d' ' -f8- \ 
    | while read -r l; do grep -x "$l" /tmp/sorted; done 

输出:

Also unique 
This line is unique 
Not unique 
Not unique 
Not unique 
Also not unique 
Also not unique 
Also not unique 
Also not unique 

----------

您也可以包围整个工作分为bash脚本:

#!/bash/bash 

sort "$1" > /tmp/sorted # $1 - the 1st argument (filename) 
uniq -u /tmp/sorted 

while read -r l; do 
    grep -x "$l" /tmp/sorted 
done < <(uniq -dc /tmp/sorted | sort -n | cut -d' ' -f8-) 
+0

这不会按出现次数排序,它只是首先放入独特的行(排序),非唯一行按字母顺序排序,而不是按频率排序。如果输入中还有几行'也不是唯一的',它应该显示在输出结尾,但不适用于此解决方案。 –

+0

只需使用这个作为你的输入文件,每个字符在一个单独的行上:'A A B B B B C C C'。显然,按频率排序,这或者必须变成“A A C C C B B B B”或者逐渐减少“B B B C C C A A”,但它将是未经修改的输入。 'uniq'不重新排列它的输入,只是对它进行过滤。 –

+0

@BenjaminW。,好吧,检查我的更新 – RomanPerekhrest

0

我会用awk计数的次数每个线路中发生数,然后打印出来(预先计划通过频率)和排序数值使用sort -n

awk 'FNR==NR{freq[$0]++; next} {print freq[$0],$0}' data.txt data.txt | sort -n 

样本输出

1 Also unique 
1 This line is unique 
2 Also not unique 
2 Also not unique 
3 Not unique 
3 Not unique 
3 Not unique 

这真是一个施瓦茨变换。如果您想放弃主频列,只需在该命令的末尾添加| cut -d ' ' -f 2-即可。

1

awk单独将是最适合您的更新问题。

$ awk '{file[$0]++; count[$1]++; max_count= count[$1]>max_count?count[$1]:max_count;} END{ k=1; for(n=1; n<=max_count; n++){ for(i in count) if(count[i]==n) ordered[k++]=i} for(j in ordered) for(line in file) if (line~ordered[j]) print line; }' file 

Alsounique zebra 
Thislineisunique cat 
Alsonotunique beaver 
Alsonotunique monkey 
Notunique parrot 
Notunique dog 
Notunique dragon 

说明:

部分-1:

{file[$0]++; count[$1]++; max_count= count[$1]>max_count?count[$1]:max_count;}

我们在存储阵列file输入文件; count数组会跟踪每个唯一第一个字段的计数,这是您希望对文件进行排序的基础。 max_count跟踪最大数量。

部分-2: 一旦AWK读完文件中,count内容将是如下:如图所示(键,值)

Alsounique 1 
Notunique 3 
Thislineisunique 1 
Alsonotunique 2 

现在我们的目标是通过数值这些键进行排序下面。这是我们关键的一步,对于下面输出中的每个字段/键/列1,我们将遍历file数组并打印包含这些键的行,它会给我们提供最终所需的输出。

Alsounique 
Thislineisunique 
Alsonotunique 
Notunique 

下面回路确实存储另一个阵列count阵列的内容的操作在sorted by values方式称为orderedordered的内容将与上面显示的输出相同。

for(n=1; n<=max_count; n++) 
    { 
     for(i in count) 
      if(count[i]==n) 
      ordered[k++]=i 
    } 

的最后一步:即遍历file阵列和存储在ordered阵列的字段的顺序打印的行。

for(field in ordered) 
    for(line in file) 
     if (line~ordered[field]) 
      print line; 
    } 

溶液-2
另一可能的解决方案将使用排序uniq的AWK /切割。但是如果你的输入文件非常大,我不会推荐使用它,因为多个管道调用多个进程会减慢整个操作。

$ cut -d ' ' -f1 file | sort | uniq -c | sort -n | awk 'FNR==NR{ordered[i++]=$2; next} {file[$0]++;} END{for(j in ordered) for(line in file) if (line~ordered[j]) print line;} ' - file 
Alsounique zebra 
Thislineisunique cat 
Alsonotunique beaver 
Alsonotunique monkey 
Notunique parrot 
Notunique dog 
Notunique dragon 

以前的解决方案(OP编辑之前的问题)

这可以通过使用sortuniqawk这样进行:

$ uniq -c <(sort f1) | sort -n | awk '{ for (i=1; i<$1; i++){print}}1' 
     1 Also unique 
     1 This line is unique 
     2 Also not unique 
     2 Also not unique 
     3 Not unique 
     3 Not unique 
     3 Not unique 
+0

非常感谢你的这一切,它完成了我正在寻找的东西!我仍然试图学习如何管理和使用多个命令来完成看起来很简单的任务,所以我可以使它适应两列工作吗?例如,如果原始输入已经 Notunique 1 Thislineisunique 2 Notunique 3 Alsonotunique 4 Alsounique 5 Alsonotunique 6 不是唯一7 而我想输出要由第一列像这样 Thislineisunique 2 排序Alsounique 5 Alsonotunique 4 Alsonotunique 6 Notunique 1 Notunique 3 Notunique 7 其中数字是只表示任何文本 – trysofter

+0

我编辑原来的职位,因此以前的评论是我n更好的格式,再次感谢你! – trysofter

+0

第一列在您的方法中是多余的 – RomanPerekhrest

相关问题