
您能給我建議如何從行或行中進行唯一排序嗎?我有這樣的訊息:
Special c1,c2,c5,c7,c1,c2
Special2 C6
Special
(這是和之間的製表符c1...
)。
我想要這樣的輸出:
Special c1,c2,c5,c7
Special2 C6
我怎樣才能做到這一點?
答案1
使用這個答案,
perl -MList::MoreUtils=uniq -laF'\t' -ne '
$F[1] = join(",", uniq(sort(split(",", $F[1])))); print join("\t", @F)'
這取決於外部包列表::更多實用工具。如果您不想安裝外部依賴項,則重新實作該uniq
功能是只需要幾行 Perl 程式碼。 (儘管我似乎已將其作為 macOS 基本系統的一部分進行安裝。)
答案2
perl -F'\t|,' -lane 'my %h; print shift @F, "\t", join ",", sort grep !$h{$_}++, @F' dataf
解釋
-F'\t|,'
@F
=> 將每個記錄欄位拆分為TAB
或字元數組comma
。-l
也會設定RS
tonewline
和ORS
tonewline
。-a
將根據FS
選擇的內容自動將每個記錄拆分為單字-F
。-n
將在輸入上設定循環讀取的隱式記錄,AND
僅在要求時才列印內容。-e
是根據上面的choenPerl
對輸入的每筆記錄執行的程式碼。RS
-l
- 第一個元素將由 給出
shift
,其餘元素將uniquified
通過將它們存儲為散列的鍵來給出,%h
每次讀入記錄時都會重新生成該散列。
答案3
使用 OpenBSD awk
、GNUawk
和進行了測試mawk
:
awk -F ',| +' '{ for (i = 2; i <= NF; ++i) { print $1, $i } }' data.in |
sort -u |
awk '{ f[$1] = (f[$1] ? f[$1] "," : "") $2 } END { for (k in f) { print k, f[k] } }'
第一個awk
將給定資料擴展為
Special c1
Special c2
Special c5
Special c7
Special c1
Special c2
Special2 C6
它使用逗號和多個空格作為字段分隔符,並且對於輸入的每個記錄(行),它在單獨的行上依次列印第一個字段,然後依次列印其他每個字段。這假設除了將被正確解釋為分隔符號的位置之外,行上沒有其他空格或逗號。
中間sort
的將其排序為
Special2 C6
Special c1
Special c2
Special c5
Special c7
它使用整行作為排序鍵進行排序,並丟棄任何重複的行。
最後awk
將數據重新組合成
Special c1,c2,c5,c7
Special2 C6
它透過使用第一個欄位作為關聯數組的鍵並將相應資料的逗號分隔串聯儲存在第二個欄位中作為值來實現此目的。最後,列印所有收集的數據。
答案4
另一種方式是一行:
while read line; do echo "$line" | awk '{print $1}' | tr '\n' ' '; echo "$line" | awk '{print $2}' | tr ',' '\n' | sort -u | tr '\n' ',' | sed -e 's/.$//g'; echo; done < file_to_sort
它採用每行的第一列 ( echo $line | awk '{print $1}' | tr '\n' ' ';
),並在將其轉換為單列後對用“,”分隔的第二列值進行排序,以便應用sort
,然後將其轉換回具有原始格式的單行 ( echo $line | awk '{print $2}' | tr ',' '\n' | sort -u | tr '\n' ','
)。
依照@tripleee的建議進行行分割:
while IFS=$'\t' read first second; do printf "%s\t%s\n" "$first" "$(tr ',' '\n' <<<"$second" | sort | tr '\n' ',' | sed -e 's/.$//g';)"; done < file_to_sort