jon*_*jon 7 awk text-processing sort csv
鉴于此文件(注释不是文件的一部分,而是构成解释的一部分)...
x,a,001,b,c,d,y
x,a,002,b,c,e,yy
x,bb,003,b,d,e,y
x,c,004,b,d,e,y
x,c,005,b,d,e,y # nb - dupe of row 4
x,dd,006,b,d,e,y
x,c,007,b,d,e,y # nb - dupe of row 4 and 5
x,dd,008,b,d,f,y
x,dd,009,b,d,e,y # nb - dupe of row 6
x,e,010,b,d,f,y
Run Code Online (Sandbox Code Playgroud)
...我想得出以下输出:
x,a,001,b,c,d,y
x,a,002,b,c,e,yy
x,bb,003,b,d,e,y
x,c,004,b,d,e,y
x,dd,006,b,d,e,y
x,dd,008,b,d,f,y
x,e,010,b,d,f,y
Run Code Online (Sandbox Code Playgroud)
如果从文件中删除第 3 列,然后在文件上运行 uniq,那么如果剩余的行在正确的位置重新添加了第 3 列的值,那么我将得到上述结果。
但我真的很挣扎,想出一些可以做到这一点的东西。我很高兴有机会了解 linux 的文本处理实用程序。
性能:文件看起来不太可能增长到超过 1MB,而且每天只有 1 个文件。
目标:Debian GNU/Linux 7 amd64,256MB/至强。
编辑:调整示例,因为字段不是固定宽度,uniq --skip-chars=n
据我所知,涉及的解决方案将不起作用。
Sté*_*las 18
使用awk
,您可以执行以下操作:
awk -F, -vOFS=, '{l=$0; $3=""}; ! ($0 in seen) {print l; seen[$0]}'
Run Code Online (Sandbox Code Playgroud)
最简单的方法:
sort -u -t, -k1,2 -k4
Run Code Online (Sandbox Code Playgroud)
-u
: 只输出第一行等号-t,
: 使用逗号作为字段分隔符-k1,2 -k4
: 仅对字段 1,2 和 4 以及其余字段排序另一种选择是在两侧重新排列数据sed
(注意 GNU 选项-r
) - 这要求记录大部分是固定长度的,否则它会失败(并且几乎不明显):
sort -u -t, -k1,2 -k4
Run Code Online (Sandbox Code Playgroud)
如果需要,您可能希望sort
在最后添加另一个以按数字-k
排序(使用该选项根据应执行的排序进行选择 - 即类似sed -k3 -t,
)
例如,在 Perl 中,您可以使用要确定唯一性的部分作为散列中的键(值整行),并仅在键尚未定义时插入到散列中。这当然比使用sed
(or awk
)灵活得多,而且写作也更多(我离 Perl Guru 还很远,所以很可能可以用更优雅的方式来完成 - 请参阅类似 Perl 的其他答案Perl 解决方案):
sed -r 's/^([^,]+,[^,]+)(,[^,]+)(.*)$/\1\3\2/' \
| sort \
| uniq -w 12 \
| sed -r 's/^([^,]+,[^,]+)(.*)(,[^,]+)$/\1\3\2/'
Run Code Online (Sandbox Code Playgroud)