3 つのテキスト ファイルから各ファイルから一意の行を見つける方法

3 つのテキスト ファイルから各ファイルから一意の行を見つける方法

固有の ID を持つ 3 つのテキスト ファイルがあり、各テキスト ファイルで固有の ID のみを保持したいと考えています。3 つのファイル (A、B、C) があるとします。A と B に「abc」という ID が含まれている場合、両方のファイルから削除する必要があります。

ファイルはソートされており、サイズは 1MB 未満で、ID は英数字です。また、各ファイル内に重複はありません。

Linux または Mac のコマンドライン ツールを使用するだけでこれを行う方法はありますか? 最初はコードを書こうと思っていましたが、まず質問したいと思いました。ありがとうございます!

答え1

前提:

  • テキストファイルには1行につき1つのIDがあります
  • 各行にはIDのみが含まれ、他のテキストは含まれません
  • IDはファイル内で重複しない
  • 出力ファイルを並べ替えても問題ありません(ソートする)
  • 実行効率は重要ではない
  • IDは英数字です
$ cat A B B C C | sort | uniq -u >A.uniq
$ cat B A A C C | sort | uniq -u >B.uniq
$ cat C A A B B | sort | uniq -u >C.uniq
$ mv A.uniq A
$ mv B.uniq B
$ mv C.uniq C

「cat」コマンドは、リストされたファイルを連結します。最初のファイルは、重複を削除したいファイルです。次のファイルは、削除したい重複の可能性があるファイルです。これらのファイルの各コピーを 2 つ追加して、重複していて削除されることを保証します。

次に、これらのファイルをアルファベット順に「ソート」します。これにより、重複した ID はソートされた出力の隣接する行に表示されます。

'-u' オプションを指定した 'uniq' コマンドは、一意の行のみを出力します。入力内の隣接する行に同じ ID が 2 つ以上出現する場合は、何も出力されません。

'>'は出力を 'A.uniq'という新しいファイルに書き込みます。

逆に、3 つのファイル内で重複しているすべての ID のリストを生成したい場合は、次のようにします。

$ cat A B C | sort | uniq -d >duplicates

'-d' フラグを指定した 'uniq' コマンドは、入力内で行が 2 回以上繰り返されている場合にのみその行を出力します。

答え2

気を紛らわせてくれてありがとう - 私は次のスクリプトを思いつきました(文書化済み) -

#! /bin/bash

SOURCEFILES="./existing/list1.txt  ./existing/list2.txt  ./existing/list3.txt"

# First find a list of duplicate files.  We do this by catting all files and finding where there are lines that are not unique

# $DUPLICATES will be a space seperated list of duplicate IDs

DUPLICATES=$( cat $SOURCEFILES | sort | uniq -d )
echo "Duplicates Found for removal: " $DUPLICATES

# Convert list of duplicates into a pipe seperated list
# Commented out version assumes all ID's are all the same length, so it would break if one is ABC and another is ABCD 
#DUPLICATES=$( echo $DUPLICATES | tr ' ' '|' )

# This version translates the duplicate REGEX to say that each line is complete 
# ^ means start of line and $ means end of line.

for each in $DUPLICATES
do
    DUPLIST="$DUPLIST^$each$|"
done

# Remove trailing "|" from DUPLIST
DUPLICATES=$( echo ${DUPLIST::-1} )


# Go through each file, removing duplicates 
for each in $SOURCEFILES
do
    mv $each $each.old
    egrep -v "$DUPLICATES" < $each.old > $each
done

関連情報