Grep due file e stampa righe con più risultati

Sep 23 2020

Ho due file.

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

(il separatore di colonna è una tabulazione)

Sto cercando di grep il file1.txtcontro in file2.txtquesto modo:

grep -w -f file1.txt file2.txt

e ottengo il seguente output:

abc     ghi
abc     xyz
mno     jkl
def     stu

Tuttavia, quello che voglio è l'output in cui sia la colonna 1 che la colonna 2 file2.txthanno hit file1.txt, in questo modo:

abc     ghi
mno     jkl

Qualsiasi aiuto sarebbe il benvenuto.

Grazie.

Dan

Risposte

3 Quasímodo Sep 23 2020 at 19:20

Salva ogni valore di file1.txtin un array a. Quindi, analizza file2.txte stampa le righe che hanno sia il primo che il secondo campo a.

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

Per un numero arbitrario di campi in file2.txt, scorrere tutti i campi ed eseguire il controllo. Se uno dei campi non è presente a, passa alla riga successiva, altrimenti stampa la riga.

awk 'NR==FNR{a[$0];next}{for(i=1;i<=NF;i++){if(!($i in a)){next}}print}' file1.txt file2.txt
RakeshSharma Sep 25 2020 at 17:09

Usando pythonpossiamo avvicinarci al pbm creando un superset bche comprende gli elementi di file1.txt.

Quindi per ogni riga da leggere file2.txtcontrolliamo se l'insieme formato da questa riga corrente è un sottoinsieme del superset b. In tal caso stampiamo la riga corrente di 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

Usando sed memorizziamo file1.txt nello spazio di attesa e quindi per ogni riga letta da File2.txt confrontiamo con la presenza di TUTTI gli elementi della riga corrente e stampiamo quando tutti trovati.

$ 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