Greppen Sie zwei Dateien und drucken Sie Zeilen mit mehreren Treffern

Greppen Sie zwei Dateien und drucken Sie Zeilen mit mehreren Treffern

Ich habe zwei Dateien.

  • file1.txt
    abc
    def
    ghi
    jkl
    mno
    pqr
    
  • file2.txt
    abc ghi
    abc xyz
    xyz xyz
    mno jkl
    def stu
    

(Spaltentrennzeichen ist Tabulator)

Ich versuche, das file1.txtGegenstück file2.txtungefähr so ​​zu greppen:

grep -w -f file1.txt file2.txt

und ich erhalte die folgende Ausgabe:

abc     ghi
abc     xyz
mno     jkl
def     stu

Was ich jedoch möchte, ist die Ausgabe, bei derbeideSpalte 1 und Spalte 2 von file2.txthaben Treffer in file1.txt, wie folgt:

abc     ghi
mno     jkl

Jede Hilfe ist willkommen.

Danke.

Dan

Antwort1

Speichern Sie jeden Wert von file1.txtin einem Array a. Analysieren file2.txtund drucken Sie dann die Zeilen, die sowohl das 1. als auch das 2. Feld in enthalten a.

awk 'NR==FNR{a[$0];next}$1 in a && $2 in a' file1.txt file2.txt

Führen Sie für eine beliebige Anzahl von Feldern in file2.txteine Schleife über alle Felder aus und führen Sie die Prüfung durch. Wenn eines der Felder nicht in enthalten ist a, fahren Sie mit der nächsten Zeile fort, andernfalls drucken Sie die Zeile.

awk 'NR==FNR{a[$0];next}{for(i=1;i<=NF;i++){if(!($i in a)){next}}print}' file1.txt file2.txt

Antwort2

Mithilfe von pythonkönnen wir uns dem PBM nähern, indem wir eine Obermenge erstellen b, die aus den Elementen von besteht file1.txt.

Dann file2.txtprüfen wir für jede gelesene Zeile, ob die aus dieser aktuellen Zeile gebildete Menge eine Teilmenge der Obermenge b ist. In diesem Fall drucken wir die aktuelle Zeile von file2.txt`

$ python3 -c 'import sys
f1, f2 = sys.argv[1:]
with open(f1) as fh1, open(f2) as fh2:
  b = set([l.strip() for l in fh1])
  print(*(l.rstrip() for l in fh2 if set(l.strip().split()).issubset(b)), sep="\n")
' file1.txt file2.txt

abc ghi
mno jkl
$ perl -lane '$. == 1 and 
    %h = map { /(.*)(\n)/ } <STDIN>;
    print if ! grep { ! $h{$_} } @F;
' file2.txt < file1.txt

Mit sed speichern wir file1.txt im Haltebereich und vergleichen dann jede aus File2.txt gelesene Zeile mit dem Vorhandensein ALLER Elemente der aktuellen Zeile und drucken, wenn alle gefunden wurden.

$ sed -Ee '
    /\n/{h;d;}
    /\s/!{H;d;}
    G;h
    s/\n.*//;s/\n//;x
    :a
      s/^\s?(\S+)((\s\S+)?\n.*\n\1(\n|$))/\2/
    ta
    s/^\n//;tb
    D;:b;x
' file1.txt file2.txt
while IFS= read -r l <&3; do
  read -r a b <<<"$l"
  grep -qFe "$a" file1.txt &&
  grep -qFe "$b" file1.txt &&
  printf '<%s>\n' "$l"
done 3< file2.txt

verwandte Informationen