我有一个很大的 csv 文件,想要建立简单的排名:
$ cat file.csv
2022-12-01 RED 1
2022-12-01 RED 1
2022-12-01 RED 2
2022-12-01 RED 2
2022-12-01 RED 2
2022-12-01 YELLOW 1
2022-12-01 YELLOW 1
2022-12-01 YELLOW 2
2022-12-01 YELLOW 2
2022-12-01 YELLOW 2
$ sort file.csv | uniq -c | sort -nr > file_sort.csv
$ cat file_sort.csv
3 2022-12-01 RED 2
3 2022-12-01 YELLOW 2
2 2022-12-01 RED 1
2 2022-12-01 YELLOW 1
我希望将结果添加为新列,但将其添加到现有的 $1 中,如下所示:
$ cut -f1 file_sort.csv
3 2022-12-01
3 2022-12-01
2 2022-12-01
2 2022-12-01
有什么方法可以将 uniq 行的值保存为新列吗?像这样:
$ cut -f1 file_sort.csv
3
3
2
2
答案1
听起来您想要做的只是将数字从第一个字段移动到最后一个字段。您没有指定这一点,但考虑到cut
您显示的命令,这应该意味着您的文件是制表符分隔的。如果是这样,鉴于uniq -c
输出将用空格填充该行(您也没有显示),并且不会在出现次数后添加制表符,您可以执行以下简单操作:
$ sort file.csv | uniq -c | sort -nr | perl -pe 's/^\s+(\d+) (.*)/$2\t$1/'
2022-12-01 YELLOW 2 3
2022-12-01 RED 2 3
2022-12-01 YELLOW 1 2
2022-12-01 RED 1 2
或者,在sed
支持-E
:
$ sort file.csv | uniq -c | sort -nr | sed -E 's/^ *([0-9]*) (.*)/\2\t\1/'
2022-12-01 YELLOW 2 3
2022-12-01 RED 2 3
2022-12-01 YELLOW 1 2
2022-12-01 RED 1 2
并且,在任何 sed 中:
$ sort file.csv | uniq -c | sort -nr | sed 's/^ *\([0-9]*\) \(.*\)/\2\t\1/'
2022-12-01 YELLOW 2 3
2022-12-01 RED 2 3
2022-12-01 YELLOW 1 2
2022-12-01 RED 1 2
或者,您可以进行计数awk
,将字段添加到您想要的位置,并在第四个字段上进行排序:
$ awk -F'\t' -v OFS='\t' '{ cnt[$0]++ }
END{
for(line in cnt){
print line,cnt[line]
}
}' file.csv | sort -nrk4,4
2022-12-01 YELLOW 2 3
2022-12-01 RED 2 3
2022-12-01 YELLOW 1 2
2022-12-01 RED 1 2
答案2
使用乐(以前称为 Perl_6)
您想要做的是Bag
元素,在本例中元素是lines
:
~$ raku -e '.say for lines.Bag;' file
输入示例(制表符分隔):
2022-12-01 RED 1
2022-12-01 RED 1
2022-12-01 RED 2
2022-12-01 RED 2
2022-12-01 RED 2
2022-12-01 YELLOW 1
2022-12-01 YELLOW 1
2022-12-01 YELLOW 2
2022-12-01 YELLOW 2
2022-12-01 YELLOW 2
示例输出:
2022-12-01 RED 2 3
2022-12-01 RED 1 2
2022-12-01 YELLOW 2 3
2022-12-01 YELLOW 1 2
注意:这里真正的问题可能是尾随空格。您可以添加一个trim-trailing
调用来消除每行右端的空格:
~$ raku -e '.put for lines.map(*.trim-trailing).Bag;'
#OR
~$ raku -e '.put for lines>>.trim-trailing.Bag;'
答案3
使用count-distinct
Miller ( ) 的子命令mlr
来计算前三个字段中具有不同值的记录数,假设输入是制表符分隔且没有列标题:
$ mlr --tsv -N count-distinct -f 1,2,3 file
2022-12-01 RED 1 2
2022-12-01 RED 2 3
2022-12-01 YELLOW 1 2
2022-12-01 YELLOW 2 3
计数将作为新字段添加到字段列表的末尾。输入不需要排序。
如果您希望计数作为第一个字段,请使用reorder
子命令。请注意,即使标题未显示在输出中,我们也可以引用操作count
创建的命名字段:count-distinct
$ mlr --tsv -N count-distinct -f 1,2,3 then reorder -f count file
2 2022-12-01 RED 1
3 2022-12-01 RED 2
2 2022-12-01 YELLOW 1
3 2022-12-01 YELLOW 2
答案4
使用 awk 命令的关联数组思想可以轻松完成对唯一行的计数:
$ awk '{a[$0]++} END {for (i in a) print a[i]"--->",i}' infile
2---> 2022-12-01 YELLOW 2
3---> 2022-12-01 RED 2
2---> 2022-12-01 YELLOW 1
1---> 2022-12-01 YELLOW 2
2---> 2022-12-01 RED 1