逆マッチングペアを削除する方法は?

逆マッチングペアを削除する方法は?

テキストファイルから重複/逆一致のペアを削除したいと思います。

たとえば、ファイルには次のデータが含まれています。

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| 

関連情報