重複した行を削除して[重複]を元に戻します。

重複した行を削除して[重複]を元に戻します。

まあ、重複した行を削除したいのですが、それよりも少し複雑です。

users.txt というファイルがあり、ファイルの例は次のとおりです。

 users:[email protected]
 users1:[email protected]

今、私のシステムのバグにより、人々は他の人と同じ電子メールアドレスで登録できるようになります。問題の例は次のとおりです。

 user:display:[email protected]
 user2:[email protected]
 user3:[email protected]
 user4:[email protected]

ユーザー、user2、user3、user4がすべて同じ電子メールを持っていることに注意してください。 user2、user3、user4を削除したいのですが、ユーザーは維持したいと思います。またはその逆(要求どおりに最初の項目を選択)、同じ電子メールを含む他の行を削​​除します。

したがって、

 [email protected] is in 20 lines remove 19
 [email protected] is in 555 lines remove 554
 and so fourth..

答え1

これにはawkが必要です。確認したいフィールドは各行の最初のフィールドなので、引用符のみを使用してください$1

awk -F: '! ($1 in seen) {print; seen[$1]}' users.txt

「ゴルフ」でこれを大幅に減らすことができます。

awk -F: '!a[$1]++' users.txt

長い形式は説明がほとんど必要ありません。値を割り当てなくても、各メールアドレスをインデックスとして使用して連想配列を構築します。その後、電子メールアドレスが以前に「見えた」(つまり、関連配列に特定の電子メールアドレスがインデックスとして含まれているかどうか)を確認し、そうでない場合は行全体を印刷できます。

短い形式は実際にはほぼ同じことを行いますが、短いコードについてはより多くの説明が必要です。

後続++演算子は変数に対して機能します。後ろに式が評価されるので、これについては後でもう一度取り上げます。

awkでは、0はfalseを意味し、0以外の場合はtrueを意味します。 !真理値を否定して反転するのです。

中括弧の外側に現れると、式はブール式として解釈され、式がtrueの場合は関連演算(中括弧内)が実行されます。明示的に指定されたアクションがないため、行全体を印刷するデフォルト(暗黙的な)アクションが使用されます。もし式はtrue(0ではない)と評価されます。

aデフォルトでは、連想配列の電子メールアドレス(最初のフィールド)を指す値をインデックスとして取得するか、存在しない場合はゼロに初期化された値を生成してゼロを偽と解釈するか、ゼロ以外を真と解釈します。裏返す結果が「true」の場合、行全体が印刷され、その時点で連想配列に格納されている値が増加します。

実際、これは十分に一般的なAwkイディオムですが、より長くより明示的なバージョンを使用してもあなたを責めることはありません。 :)

答え2

  1. 使用牛に似た一種の栄養 datamashグループ入力2位フィールドを選択し、各グループ化の最初の行のみを保持します。

    datamash -t':' -g 2 rmdup 2 < users.txt
    
  2. さんの意見ではドンクリスティコメントはsortこれを実行できますが、目的の結果を返すときに出力の順序を変更することもできます。

    sort -t':' -k 2,2 -u users.txt
    

上記のコードは次のように仮定します。ユーザー.txt2番目のフィールドでソートし、最初のフィールドでソートします。

関連情報