Text-Processing
uniq 一個忽略列的 csv 文件,可能是 awk 嗎?
給定這個文件(註釋不是文件的一部分,而是解釋的一部分)……
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
…我想得出以下輸出:
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
如果從文件中刪除第 3 列,然後在文件上執行 uniq,那麼如果剩餘的行將它們的第 3 列值添加回正確的位置,那麼我將得到上述結果。
但我真的很掙扎,想出一些能做到這一點的東西。我很高興有機會了解 linux 的文本處理實用程序。
性能:文件看起來不會增長到超過 1MB,而且每天只有 1 個文件。
目標:Debian GNU/Linux 7 amd64, 256MB / Xeon。
編輯:調整範例,因為欄位不是固定寬度,
uniq --skip-chars=n
據我所知,涉及的解決方案將不起作用。
使用
awk
,您可以執行以下操作:awk -F, -vOFS=, '{l=$0; $3=""}; ! ($0 in seen) {print l; seen[$0]}'
最簡單的方法:
sort -u -t, -k1,2 -k4
-u
: 只輸出等號的第一行-t,
: 使用逗號作為欄位分隔符-k1,2 -k4
:僅對欄位 1,2 和 4 以及其餘欄位進行排序另一種選擇是在兩側使用
sed
(注意 GNU 選項)重新排列數據 - 這要求記錄大部分是固定長度的,否則它將失敗(並且幾乎不明顯):-r
sed -r 's/^([^,]+,[^,]+)(,[^,]+)(.*)$/\1\3\2/' \ | sort \ | uniq -w 12 \ | sed -r 's/^([^,]+,[^,]+)(.*)(,[^,]+)$/\1\3\2/'
如果需要,您可能希望
sort
在最後添加另一個以按數字排序(使用-k
選項根據應執行的排序進行選擇 - 即類似的東西sed -k3 -t,
)例如,在 Perl 中,您可以使用要確定唯一性的部分作為散列中的鍵(值是整行),並且僅當鍵尚未定義時才插入散列中。這當然比使用
sed
(orawk
) 靈活得多,而且寫作也更多(我離 Perl Guru 還很遠,所以很可能它可以以更優雅的方式完成 - 請參閱 Perl-like 的其他答案Perl 解決方案):#!/usr/bin/perl use strict; my %lines; while (<>) { (my $k1, my $v, my $k2) = /^([^,]+,[^,]+,)([^,]+)(,.*)$/; my $k = $k1 . $k2; if (!exists($lines{$k})) { $lines{$k} = $_; } } for my $k (sort(keys(%lines))) { print $lines{$k}; }