何百万ものレコードを含むことができるパイプで区切られたファイルがあります。私が望むのは、ファイルをソートし、ファイルに重複した行がある場合は削除することです。
次に、最初の32列を確認して、最初の行の内容が2番目の行と一致することを確認する必要があります。その場合は、2行目を削除し、1行目と3行目をもう一度確認してください(以前の行が削除されたので、同じので2行目になります)。同じ場合、3 行目も削除し、矛盾が発生するまで最初の行をファイルの次の行と比較し続けます。例: 入力ファイル:
a|a1|a2|a3|a4|...|a32|[email protected]
a|a1|a2|a3|a4|...|a32|[email protected]$1553:2015-02-14
a|a1|a2|a3|a4|...|a32|[email protected]:2015-03-01
a|a1|a2|a3|a4|...|a32|[email protected]$121:2015-01-31
a|a1|a2|a3|a4|...|a32|[email protected]$293:2015-02-28
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24
b|b1|b2|b3|b4|...|b32|[email protected]:2013:05:24
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24
b|b1|b2|b3|b4|...|b32|[email protected]:2014:05:24
c|c1|c2|c3|c4|...|c32|[email protected]
c|c1|c2|c3|c4|...|c32|$200:2011:12:06
c|c1|c2|c3|c4|...|c32|[email protected]$214:2001:01:31
上記の例には33のフィールドがあり、「...」は連続性を示すために使用されます。したがって、見てわかるように、最初の4行は同じです(例では、「a32」と表示されているフィールド番号32のみが比較されます)。したがって、最初の項目だけを保持し、残りの項目を削除するだけです。繰り返しますが、で始まる列にはb
5つの同じレコードがあるため、最後の4つをもう一度削除して最初のレコードを保持します。で始まるレコードの場合はc
3つのレコードしかないため、最後の2つは削除し、最初のものは維持する必要があります。したがって、出力ファイルは次のようになります。
必須出力ファイル:
a|a1|a2|a3|a4|...|a32|[email protected]
b|b1|b2|b3|b4|...|b32|[email protected]$542:2013:05:24
c|c1|c2|c3|c4|...|c32|[email protected]
これを行うには、通常のループとsedコマンドを使用することを検討していますが、プロセスが大幅に遅くなります。それでは、ack
この検索/タスクをより迅速に使用する方法はありますか?
答え1
キー1から32までの並べ替え(-k1,32)垂直ストリップ区切り記号として-t'|'
。
-u
意味:同じ実行(キーの組み合わせ)の最初の行のみを出力します。詳細については、
オプションを参照してください man sort
。sort
sort -t'|' -k1,32 -u infile
もちろん、上記のコードはソートされた出力を生成します。
ただし、入力ファイルのように最初に見つかった行の順序を同じにするには、次のようにします。
nl -s'|' -ba infile | sort -t'|' -k2,5 -u | sort -t'|' -k1 -n | cut -d'|' -f2-
nl
連続した行番号をプレフィックスとして使用してください。この行番号は次のcut
手順に従いますsort
。
2番目の方法の出力は次のとおりです。テデンパールソリューション。
答え2
ピーターのsort
方法はほとんど間違いなく最も効果的であるため、使用することをお勧めします。多様性のために、Perlソリューションは次のとおりです。
perl -F"\|" -lane 'push @G,$_ unless ++$k{join("\|",@F[0..31])}>1;
END{print join "\n",@G}' file