GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie entferne ich die Zeilen, die in Datei B erscheinen, aus einer anderen Datei A?

Wenn die Dateien sortiert sind (in Ihrem Beispiel):

comm -23 file1 file2

-23 unterdrückt die Zeilen, die sich in beiden Dateien oder nur in Datei 2 befinden. Wenn die Dateien nicht sortiert sind, leiten Sie sie durch sort zuerst...

Sehen Sie sich die Manpage hier an


awk zur Rettung!

Diese Lösung erfordert keine sortierten Eingaben. Sie müssen zuerst fileB bereitstellen.

awk 'NR==FNR{a[$0];next} !($0 in a)' fileB fileA

zurück

A
C

Wie funktioniert es?

NR==FNR{a[$0];next} Idiom dient zum Speichern der ersten Datei in einem assoziativen Array als Schlüssel für einen späteren "Contains"-Test.

NR==FNR prüft, ob wir die erste Datei scannen, wobei der globale Zeilenzähler (NR) gleich dem Zeilenzähler der aktuellen Datei (FNR) ist.

a[$0] fügt die aktuelle Zeile als Schlüssel zum assoziativen Array hinzu, beachten Sie, dass sich dies wie eine Menge verhält, bei der es keine doppelten Werte (Schlüssel) gibt

!($0 in a) wir sind jetzt in der/den nächsten Datei(en), in ist ein Contains-Test, hier wird überprüft, ob die aktuelle Zeile in der Menge ist, die wir im ersten Schritt aus der ersten Datei ! gefüllt haben negiert die Bedingung. Was hier fehlt, ist die Aktion, die standardmäßig {print} ist und normalerweise nicht explizit geschrieben.

Beachten Sie, dass dies jetzt verwendet werden kann, um Wörter auf der schwarzen Liste zu entfernen.

$ awk '...' badwords allwords > goodwords

mit einer kleinen Änderung kann es mehrere Listen bereinigen und bereinigte Versionen erstellen.

$ awk 'NR==FNR{a[$0];next} !($0 in a){print > FILENAME".clean"}' bad file1 file2 file3 ...

Eine andere Möglichkeit, dasselbe zu tun (erfordert auch eine sortierte Eingabe):

join -v 1 fileA fileB

In Bash, wenn die Dateien nicht vorsortiert sind:

join -v 1 <(sort fileA) <(sort fileB)

grep -Fvxf <lines-to-remove> <all-lines>

  • funktioniert mit nicht sortierten Dateien (im Gegensatz zu comm )
  • hält die Ordnung ein
  • ist POSIX

Beispiel:

cat <<EOF > A
b
1
a
0
01
b
1
EOF

cat <<EOF > B
0
1
EOF

grep -Fvxf B A

Ausgabe:

b
a
01
b

Erklärung:

  • -F :Verwenden Sie Literal-Strings anstelle des Standard-BRE
  • -x :Nur Übereinstimmungen berücksichtigen, die mit der gesamten Zeile übereinstimmen
  • -v :print non-matching
  • -f file :Muster aus der gegebenen Datei nehmen

Diese Methode ist bei vorsortierten Dateien langsamer als andere Methoden, da sie allgemeiner ist. Wenn es auch auf die Geschwindigkeit ankommt, siehe:Schneller Weg, Zeilen in einer Datei zu finden, die in einer anderen nicht sind?

Hier ist eine schnelle Bash-Automatisierung für den Inline-Betrieb:

remove-lines() (
  remove_lines="$1"
  all_lines="$2"
  tmp_file="$(mktemp)"
  grep -Fvxf "$remove_lines" "$all_lines" > "$tmp_file"
  mv "$tmp_file" "$all_lines"
)

GitHub-Upstream.

Verwendung:

remove-lines lines-to-remove remove-from-this-file

Siehe auch:https://unix.stackexchange.com/questions/28158/is-there-a-tool-to-get-the-lines-in-one-file-that-are-not-in-another


Linux
  1. Zeilen aus Textdatei auswählen, deren IDs in einer anderen Datei aufgeführt sind?

  2. Wie entferne ich die Bom aus einer UTF-8-Datei?

  3. Wie entferne ich X Bytes vom Ende einer großen Datei, ohne die gesamte Datei zu lesen?

  4. So verwenden Sie sed, um die letzten n Zeilen einer Datei zu entfernen

  5. Entfernt die ersten N Zeilen aus einer aktiven Protokolldatei

So entfernen Sie ein Passwort aus einer PDF-Datei unter Linux

So entpacken Sie die gz-Dateien unter Linux

So entfernen Sie Zeilen aus einer Datei mit dem Sed-Befehl

So entfernen Sie (^M) Zeichen aus einer Datei in Linux

So löschen Sie Dateien, die in einer anderen Datei unter Linux aufgeführt sind

Wie kopiert man eine Datei aus einem anderen Verzeichnis in das aktuelle?