unix コマンドを使用して各行の固有値を取得します。

unix コマンドを使用して各行の固有値を取得します。

次のリストがあります。

1 2 5 2
1 5 5 3
1 5 5 5
5 2 2 2
2 2 4 3

各行を並べ替えて、次の一意の値を取得したいと思いますsort | uniq

1 2 5
1 3 5
1 5
2 5
2 3 4

オンラインでソリューションを探していますが、列で並べ替えるソリューションのみを見つけることができます。どのように出力を取得できますか?よろしくお願いします。

答え1

行内の列よりも行をソートする方が簡単なので、1つのアプローチは各行を転置して(各フィールドが行になるように)適用してから転置するsortことuniqです。

以下は、GNUツールを想定した簡単な実装です。

$ while read -r line; do echo "$line" | grep -o '[^ ]*' | sort -h | uniq | paste -s; done <file

file各行に対してループを介して、次の操作を行います。

  • grep-oオプション(各行の一致する部分のみを印刷)を使用して入力を次に分割します。N一致する部分文字列ごとに1つずつ。ここでは、スペースを除くすべての項目を一致させます。
  • 分割線は、-h人間が読める数字を比較するオプションを使用してソートされます(フィールドを英数字文字列でソートするには、このオプションを削除します-h)。
  • このuniqコマンドは重複した項目を削除します。
  • paste -s標準入力の各行を、タブ区切りの単一行フィールドとして印刷します。末尾の| tr '\t' ' '文字を追加してタブを空白に変更できます。

しかし、ループを使用してテキストを処理することは通常悪い習慣と考える

答え2

以下は、複数の列にわたってデータを並べ替えるのではなく、一意の値のみを抽出します。ソートが必要かどうかは不明です。

使用awk:

$ awk '{ n=split($0,a,FS); $0=""; j=1; delete u; for (i=1; i<=n; i++) if (!u[a[i]]++) $(j++) = a[i]; print }' <file
1 2 5
1 5 3
1 5
5 2
2 4 3

このプログラムは、コメントと一緒に見事に構成されています。

{
    # split the current record into fields in the array a
    n = split($0, a, FS)

    # empty the current record
    $0=""

    # j is the next field number that we are to set
    # in the record that we are building
    j=1

    # seen is an associative array that we use to
    # keep track of whether we've seen a bit of
    # data before from this record
    delete seen

    # loop over the entries in a (the original
    # fields of the input data)
    for (i=1; i<=n; i++)
        # if we haven't seen this data before,
        # mark it as seen and...
        if (!seen[a[i]]++)
            # add it to the j:th field in the new record
            $(j++) = a[i]

    print
}

ここで私の考えは、元のデータの一意のフィールドを含む各入力行の出力レコードを作成することです。

デフォルトでは、「record」は「row」と同義語、「field」は「column」と同義語です(これは、およびの現在の値に応じてより一般的な単語にすぎませんRSFS

答え3

パールの使用:

perl -MList::Util=uniq -alne 'print join " ", sort { $a <=> $b } uniq @F' file
1 2 5
1 3 5
1 5
2 5
2 3 4

答え4

bash@fra-sanのアプローチに似た別のアプローチです。

while read X;do tr<<<$X ' ' \\n|sort -u|paste -sd" ";done<file
1 2 5
1 3 5
1 5
2 5
2 3 4

関連情報