各列に固有の値を保持します(カンマで区切られます)。

各列に固有の値を保持します(カンマで区切られます)。

.tsvLinuxシステムには、さまざまなタイプ(文字列、数字)のカンマ区切り値を含む次の列を含む(タブ区切り列)ファイルがあります。

col1    col2    
.       NS,NS,NS,true,true      
.       12,12,12,13 
1,1,1,2 door,door,1,1   

独自の価値を維持したいと思います(残念ながら試しましたが失敗しました)。出力は次のとおりです。

col1 col2   
.    NS,true        
.    12,13  
1,2  door,1 

答え1

これは、値文字列を整数インデックスマップに分割して結合するMillerバリアントです。カンマ区切り文字列に戻る):

mlr --tsv put 'for (k,v in $*) {
  $[k] =  joink(apply(splitnvx(v,","), func(k,v) {return{v:k}}),",")
}' file.tsv

またはperl5の助けを借りてリスト::ユーティリティ基準寸法:

perl -MList::Util=uniq -F'\t' -lpe '
  $_ = join "\t", map { join ",", uniq split /,/, $_ } @F
' file.tsv

答え2

使用ミラーmlr)は各入力レコードのタブ区切りフィールドを繰り返し、フィールド値をコンマに分割し、各結果文字列を名前付きマップのキーとして追加し、最後にオーバーライドする区切り文字seenとしてコンマを使用してマップを連結します。します。フィールドseen:

$ mlr --tsv put 'for (k,v in $*) { seen={}; for (i in splitax(v,",")) { seen[i]=1 } $[k] = joink(seen,",") }' file
col1    col2
.       NS,true
.       12,13
1,2     door,1

ミラーのput表情が美しくプリントされています。

for (k, v in $*) {
    seen = {};
    for (i in splitax(v, ",")) {
        seen[i] = 1
    }
    $[k] = joink(seen, ",")
}

分割値をマップのキーとして追加すると、重複がなくなります。このsplitax()関数は、各結果項目の型を推論することなく、区切り文字の文字列を配列に分割します(文字列になります)。このjoink()関数はマップのキーを一緒に連結して、指定された区切り文字で区切られた文字列を形成します。外部ループのk合計値は、vそれぞれフィールド名とその値です。

答え3

薄暗いPerlアプローチは次のとおりです。

$ perl -F'\t' -le '
%k=%l={}; 
print join("\t", 
  join(",",grep{++$k{$_}==1}split(/,/,$F[0])), 
  join(",",grep{++$l{$_}==1}split(/,/,$F[1]))
)' file.tsv
col1    col2
.   NS,true
.   12,13
1,2 door,1

答え4

次のプログラムが実行されます(配列(1)awk操作をサポートするすべての最近のAwk実装で動作する必要があります):delete

BEGIN{FS=OFS="\t"}

{
    for (i=1;i<=NF;i++)
    {
        n=split($i,sf,",")
        delete seen
        fld=""

        for (j=1;j<=n;j++)
        {
            if (!seen[sf[j]]++)
            {
                fld=fld (fld?",":"") sf[j]
            }
        }
        $i=fld
    }
    print
}

たとえば、次のように保存してdedup.awk呼び出します。

awk -f dedup.awk input.tsv

入力ファイルで作業します。

これにより、\t入力フィールドと出力フィールドの区切り文字が設定されます。それではそうです。

  • for (i=1;i<=NF;i++)行のすべてのフィールドを繰り返す()
  • 各フィールドをサブフィールドに分割( sf),
  • すべてのサブフィールドを繰り返し、フィールドを一時変数として再組み立てしますfldが、まだフィールドに表示されていないサブフィールド値のみを追加します。配列にレコードを保存しますseen
  • 最後に再組み立てられたフィールドをfld現在のフィールドに割り当てます。$i
  • これまでのすべての修正を含むライン全体を印刷します。

(1)最近サポートがかなり広がっていることを暗示してくれた@EdMortonに感謝します。

関連情報