awkの行内で左から右にソートする方法は?

awkの行内で左から右にソートする方法は?

XMLタイプタグを含む大容量データファイルがあります。各行は一意の項目を参照し、さまざまな数の属性フィールドを含みます。その行の番号付きラベルに基づいて、行を最も低いものから最も高いものまで並べ替え、重複する項目を削除する必要があります。 awkを使用して各行でこれを実行できますか?

<ITEM ID='81'>,< 1>KWIKSET</1>,< 2>PASS</2>,< 7>KNOB</7>,< 5a>RIGHT</5a>,< 8c>BRASS</8c>,< 2>TYLO</2>,< 2>PASS</2>,< 5a>RIGHT</5a>,< 8c>BRASS</8c>
<ITEM ID='82'>,< 1>KWIKSET</1>,< 4a>PRIVACY</4a>,< 7>KNOB</7>,< 8b>SATIN</8b>,< 8c>CHROME</8c>,< 2>TYLO</2>,< 4a>PRIVACY</4a>,< 8b>SATIN</8b>,< 8c>CHROME</8c>
<ITEM ID='83'>,< 1>KWIKSET</1>,< 8b>POLISHED</8b>,< 8c>BRASS</8c>

答え1

私はこれにPerlを使います:

perl -MList::Util=uniq -F, -lane '
    $item = shift @F;
    @fields = uniq sort @F;
    print join ",", $item, @fields;
' file

出力:

<ITEM ID='81'>,< 1>KWIKSET</1>,< 2>PASS</2>,< 2>TYLO</2>,< 5a>RIGHT</5a>,< 7>KNOB</7>,< 8c>BRASS</8c>
<ITEM ID='82'>,< 1>KWIKSET</1>,< 2>TYLO</2>,< 4a>PRIVACY</4a>,< 7>KNOB</7>,< 8b>SATIN</8b>,< 8c>CHROME</8c>
<ITEM ID='83'>,< 1>KWIKSET</1>,< 8b>POLISHED</8b>,< 8c>BRASS</8c>

行を理解するのがより難しく書くこともできます。

perl -MList::Util=uniq -F, -lape '$"=","; $_="@{[$F[0], uniq sort @F[1..$#F]]}"' file

タグの内容にカンマが含まれていないことを願っています。

答え2

awkだけを使う理由はありますか?問題を解決するには、まずデータを各単位に分割して並べ替え、重複項目を削除してから再結合する必要があります。最も有能なプログラミング言語またはスクリプト言語(Cも含む)を使用してこれを実行できますが、必要な作業を実行するためのツールがすでにある場合は再開発する価値はありますか?

公開するデータが作業中のデータを実際に表現している場合は、次を使用してすばやく処理できます。

$ cat RAW_DATA
<ITEM ID='81'>,< 1>KWIKSET</1>,< 2>PASS</2>,< 7>KNOB</7>,< 5a>RIGHT</5a>,< 8c>BRASS</8c>,< 2>TYLO</2>,< 2>PASS</2>,< 5a>RIGHT</5a>,< 8c>BRASS</8c>
<ITEM ID='82'>,< 1>KWIKSET</1>,< 4a>PRIVACY</4a>,< 7>KNOB</7>,< 8b>SATIN</8b>,< 8c>CHROME</8c>,< 2>TYLO</2>,< 4a>PRIVACY</4a>,< 8b>SATIN</8b>,< 8c>CHROME</8c>
<ITEM ID='83'>,< 1>KWIKSET</1>,< 8b>POLISHED</8b>,< 8c>BRASS</8c>
$ while read line; do echo "$(cut -d, -f1 <<< "$line"),$(cut -d, -f2- <<< "$line" | tr ',' '\n' | sort -n | uniq | paste -sd,)"; done < RAW_DATA
<ITEM ID='81'>,< 1>KWIKSET</1>,< 2>PASS</2>,< 2>TYLO</2>,< 5a>RIGHT</5a>,< 7>KNOB</7>,< 8c>BRASS</8c>
<ITEM ID='82'>,< 1>KWIKSET</1>,< 2>TYLO</2>,< 4a>PRIVACY</4a>,< 7>KNOB</7>,< 8b>SATIN</8b>,< 8c>CHROME</8c>
<ITEM ID='83'>,< 1>KWIKSET</1>,< 8b>POLISHED</8b>,< 8c>BRASS</8c>

このwhileループはファイルの各行を読み取り、個別に処理します。次に、cut -d, -f1 <<< "$line"最初のフィールドだけが抽出される(静的であるため)、新しい行をエコーし​​、残りのフィールドを抽出し、数値cut -d, -f2- <<< "$line" | tr ',' '\n' | sort -n | uniq | paste -sd,で並べ替え、一意の値をフィルタリングし、カンマ区切りpaste -sd,リストを再結合するために使用します。

関連情報