テキストファイルから重複/逆一致のペアを削除したいと思います。
たとえば、ファイルには次のデータが含まれています。
10 |Name1 |20 |Name2
20 |Name2 |30 |Name3
20 |Name2 |10 |Name1 <-- Inverse pair (compared to first line) to be removed from text file
40 |Name4 |30 |Name3
私は次の結果を期待しています:
10 |Name1 |20 |Name2
20 |Name2 |30 |Name3
40 |Name4 |30 |Name3
答え1
awkを使用してください:
awk -F '[[:blank:]]*[|][[:blank:]]*' -v SUBSEP='|' '
($1,$2,$3,$4) in seen || ($3,$4,$1,$2) in seen {next}
{seen[$1,$2,$3,$4]; print}
' file
フィールド区切り文字を、オプションの先頭または末尾のスペースを含むパイプ文字に設定します。次に、連想配列キーとして任意の順序で「ペア」を探します。見つかった場合はその行をスキップし、そうでない場合はキーが配列に追加され、その行が印刷されます。
答え2
たぶん、次のようなものがあります。
perl -F'[|]' -lane '
for (@F) {
# trim the fields to remove leading and trailing blanks
s/^\s+//; s/\s+$//
}
# re-join the trimmed fields into $a
my $a = join "|", @F[0..3];
# same, inverting the two pairs into $b
my $b = join "|", @F[2,3,0,1];
# print unless either $a or $b has been seen before
print unless $seen{$a} || $seen{$b}++' < your-file
%seen
任意の順序で見つかった任意の数のペアを一般化するには、ペアをソートして連想配列のキーを形成する必要があります。
perl -F'[|]' -lane '
for (@F) {
# trim the fields to remove leading and trailing blanks
s/^\s+//; s/\s+$//
}
my @pairs;
while (my ($a, $b) = splice(@F, 0, 2)) {
push @pairs, "$a|$b"
}
my $key = join "|", sort @pairs;
print unless $seen{$key}++' < your-file
答え3
これを行うには、sedを使用できます。以下のコードはgnu sedを使用しますが、簡単にposixと互換性があるようにすることができます。
sed -Ee '
$!{
s/$/|/
N
s/[[:blank:]]+//g
H;s/.*//;x;D
}
s/$/|/
G;H;g
y/\n_/_\n/
:xdup
s/_((([^_|]+[|]){2})(([^_|]+[|]){2}))_(.*_)?\4\2_/_\1_\6/
txdup
s/^_//;s/_$//
y/\n_/_\n/
' input.csv
出退勤時間が近づくと後で説明します。
結果:
10|Name1|20|Name2|
20|Name2|30|Name3|
40|Name4|30|Name3|