So finden Sie eindeutige Zeilen aus jeder Datei mit 3 Textdateien

So finden Sie eindeutige Zeilen aus jeder Datei mit 3 Textdateien

Ich habe 3 Textdateien mit einigen eindeutigen IDs und möchte in jeder Textdatei nur eindeutige IDs behalten. Nehmen wir an, es gibt 3 Dateien (A, B und C). Wenn in A und B die ID „abc“ vorkommt, muss sie aus beiden Dateien entfernt werden.

Die Dateien sind sortiert und kleiner als 1 MB. Die IDs bestehen aus alphanumerischen Zeichen. Innerhalb der einzelnen Dateien gibt es keine Duplikate.

Gibt es eine Möglichkeit, dies nur mit Befehlszeilentools unter Linux oder Mac zu tun? Ich dachte zunächst daran, einen Code zu schreiben, wollte aber zuerst fragen. Danke!

Antwort1

Annahmen:

  • die Textdateien haben eine einzelne ID pro Zeile
  • jede Zeile enthält nur eine ID und keinen anderen Text
  • die IDs werden innerhalb einer Datei nicht wiederholt
  • es ist OK, die Ausgabedatei neu anzuordnen (sortieren)
  • Ausführungseffizienz ist nicht wichtig
  • IDs sind alphanumerisch
$ 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

Der Befehl „cat“ verknüpft die aufgelisteten Dateien miteinander. Die erste Datei ist die, die ich von Duplikaten befreien möchte. Die nächsten Dateien sind die potenziellen Duplikate, die ich entfernen möchte. Ich füge zwei Kopien jeder dieser Dateien hinzu, um sicherzustellen, dass sie Duplikate sind und entfernt werden.

Als nächstes sortiere ich diese Dateien alphabetisch. Dadurch erscheinen alle doppelten IDs in der sortierten Ausgabe in benachbarten Zeilen.

Der Befehl „uniq“ mit der Option „-u“ gibt nur Zeilen aus, die eindeutig sind. Wenn in der Eingabe zwei oder mehr gleiche IDs in benachbarten Zeilen vorkommen, wird nichts ausgegeben.

Das '>' schreibt die Ausgabe in eine neue Datei namens 'A.uniq'

Wenn Sie das Gegenteil tun und eine Liste aller IDs erstellen möchten, die in den drei Dateien doppelt vorkommen, könnten Sie Folgendes tun:

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

Der Befehl „uniq“ mit dem Flag „-d“ gibt nur dann eine Zeile aus, wenn sie in der Eingabe zwei oder mehr Mal wiederholt wird.

Antwort2

Danke für die Ablenkung - ich habe mir das folgende Skript ausgedacht (dokumentiert) -

#! /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

verwandte Informationen