説明する

説明する

次のファイルがあります。

AA,true
AA,false
BB,false
CC,false
BB,true
DD,true

重複した項目を見つけて、同じ列値を持つ行を削除しようとしていますtrue

出力は次のようになります。

AA,false
BB,false
CC,false
DD,true

答え1

簡単なバージョン:

sort input.txt | awk -F, '!a[$1]++'

「false」は「true」の前にアルファベット順にソートされます。ここで、Awkコマンドはそれぞれの一意の最初のフィールド値の最初の行のみを保持します。

「true」を維持し、「false」を維持したくない場合は、逆並べ替えて同じAwkコマンドに渡してから再配置します。

答え2

awk -F, '$2 == "false" {data[$1]=$2 } $2=="true" { if ( data[$1]!="false" ) { data[$1]=$2 } } END { OFS=","; for (item in data) { print item,data[item] }}' input

説明のためにスクリプトを垂直方向に展開します。

BEGIN {
   FS=","         # Set the input separator; this is what -F, does.
}
$2 == "false" {    # For any line whose second field is "false", we
   data[$1]=$2     # will use that value no matter what.
}
$2=="true" {                    # For lines whose second field is "true",
   if ( data[$1]!="false" ) {   # only keep if if we haven't yet seen a
      data[$1]=$2               # "false"
   }
}
END {                           # Now that we have tabulated our data, we
   OFS=","                      # can print it out by iterating through 
   for (item in data) {         # the array we created.
      print item,data[item]
   }
}

答え3

perl -F, -lane '
   exists $h{$F[0]} or $h[$h{$F[0]}=@h]=$_;
   $h=$_; /,false$/ or $_=$h for $h[$h{$F[0]}];
   END{ print for @h; }
' duplicates.file

データ構造:

  • キーは最初のフィールド(AAA、BBB、CCCなど)のハッシュで%hあり、その値はキーが発生した順序を示す数値です。たとえば、AAAキー=>0、BBBキー=>1、CCCキー=>2です。
  • @hその要素は、印刷順序に含まれる行の配列です。したがって、データで true と false の両方が見つかると、false 値が配列に格納されます。 OTW、データ型がある場合は存在します。

別の方法はGNU sedを使用することです。

sed -Ee '
   G
   /^([^,]*),(false|true)\n(.*\n)?\1,\2(\n|$)/ba
   /^([^,]*)(,true)\n(.*\n)?\1,false(\n|$)/ba
   /^([^,]*)(,false)\n((.*\n)?)\1,true(\n|$)/{
      s//\3\1\2\5/;h;ba
   }
   s/([^\n]*)\n(.*)$/\2\n\1/;s/^\n*//
   h;:a;$!d;g
' duplicates.file

FWIW、上記のGNU-sedコードに対応するPOSIXは次のとおりです。

sed -e '
   G

   /^\([^,]*\),\(false\)\n\(.*\n\)\{0,1\}\1,\2$/ba
   /^\([^,]*\),\(false\)\n\(.*\n\)\{0,1\}\1,\2\n/ba

   /^\([^,]*\),\(true\)\n\(.*\n\)\{0,1\}\1,\2$/ba
   /^\([^,]*\),\(true\)\n\(.*\n\)\{0,1\}\1,\2\n/ba

   /^\([^,]*\),true\n\(.*\n\)\{0,1\}\1,false$/ba
   /^\([^,]*\),true\n\(.*\n\)\{0,1\}\1,false\n/ba

   /^\([^,]*\)\(,false\)\n\(\(.*\n\)\{0,1\}\)\1,true$/{
      s//\3\1\2/
      h
      ba
   }
   /^\([^,]*\)\(,false\)\n\(\(.*\n\)\{0,1\}\)\1,true\n/{
      s//\3\1\2\n/
      h
      ba
   }

   y/\n_/_\n/
   s/\([^_]*\)_\(.*\)$/\2_\1/;s/^_*//
   y/\n_/_\n/

   h;:a;$!d;g
' duplicates.file

説明する

  • この方法では、印刷する最終結果をアーカイブスペースに保存します。
  • 読み取った行ごとに、ホールド空間をパターン空間に追加して、ホールド空間に基づいて現在の行の既存の状態を確認します。
  • これで、比較中に5つのことが発生する可能性があります。
    • a)現在の行は予約された行のどこかに一致し、false:falseです。
      • [対処] 同じエラー状態が見つかり、何もしません。
    • b) 現在の行は保持される行のどこかに一致し、 true:true です。
      • [対処] これで同じ実態が見つかりましたので何もしないでください。
    • c)現在の行はメンテナンスラインのどこかに一致し、true:falseです。
      • [対処] 既にエラー状態が存在し、何もしません。
    • d)現在の行は予約された行のどこかに一致し、false:trueです。
      • [対処] 実際のワイヤとまったく同じ位置に偽のワイヤを交換する必要があるため、少し作業が必要です。
    • e) 現在のラインがホールドラインのどの位置とも一致しない。
      • [動作]現在の行を最後に移動します。

結果

AA,false
BB,false
CC,false
DD,true

答え4

2段階sortソリューション

sort -k1,1 -k2,2 -t, file | sort -k1,1 -t, -u

最初のsortパスはレコードをフィールドごとにクラスタリングし、各レコードブロックの前のレコードは共通フィールド値を共有します。 2番目のパスは、フィールド内の各固有値のレコードを生成するように設定されます。安定した順序を意味するため、生成される1つのレコードは、フィールド内の各固有値に対して見つかった最初のレコードです。これは、最初のパスで行われた操作のために2番目のフィールドのレコードです。1falsetrue1sort1-u-u1falsesort

関連情報