"Ungrep" - quali schemi non corrispondono


13

Sto cercando un comando o uno script per fare quanto segue - dato:

file1.txt:

abcd
efgh 
ijkl
mnop

file2.txt:

123abcd123
123efgh123
123mnop123

Voglio un comando che faccia qualcosa del genere:

ungrep file1.txt file2.txt

e restituisce quanto segue:

ijkl

In altre parole, mi sta dando le righe in file1.txt che non restituirà alcun risultato su un grep di file2.txt. So che posso farlo iterando attraverso file1.txt, grepping file2.txt per ogni riga e memorizzando il risultato, e producendo tutte le righe in cui il risultato è vuoto, ma speravo in un modo più efficiente per farlo.

Risposte:


18

Con GNU grepdovrebbe funzionare quanto segue. Usando l' -fopzione, passa file1.txtcome "file modello", ma passa anche una seconda volta come file di dati. Utilizzare -oper segnalare solo le parti corrispondenti. Infine estrae quelle parole che corrispondono una sola volta: queste corrispondono alle righe da file1.txtcui non trova corrispondenza file2.txt.

grep -h -o -f  file1.txt file2.txt file1.txt | sort | uniq -u
ijkl

Ottima descrizione Grazie e +1.
Unxnut

4
Potresti ottenere lo stesso effetto senza la delicatezza del grep: sort file1.txt <(grep -of file1.txt file2.txt) | uniq -uma, come la tua soluzione, funziona solo quando il file di pattern non contiene effettivamente metacaratteri regex.
rici,

@rici, questo è un ottimo punto
iruvar

2
Miglioramento:grep -oFf file1.txt file2.txt | sort file1.txt - | uniq -u
Stéphane Chazelas,

10

Potresti farlo awkcome:

awk '
  NR == FNR {w[$0]; next}
  {for (i in w) if (index($0,i)) delete w[i]}
  END {for (i in w) print i}' file1.txt file2.txt

Usando index, stiamo cercando sottostringhe anziché abbinare espressioni regolari.

Poiché eliminiamo la parola dall'array non appena troviamo una corrispondenza, evitiamo ricerche non necessarie.


1
Accetterei solo questo. Non invoca alcun ordinamento O (n log n) e non fallisce in modo strano quando i pattern contengono meta-caratteri regex e potrebbero essere estesi per supportare regex.
Kaz,

Non riesco a credere che la semplice valutazione w[$0]abbia l'effetto collaterale di aggiungere la chiave all'array.
Kaz,

1
@Kaz, sì, può essere fonte di confusione, e trovi molti script che non allocano consapevolmente gli elementi dell'array facendo involontariamente if (a[$1])invece che if ($1 in a)ad esempio. È il caso di ogni awkincluso l'originale awke nawk, ma guardando lo standard di ieri, non sono riuscito a trovarlo specificato.
Stéphane Chazelas,

1
@Kaz Ecco la citazione POSIX: "La domanda deve garantire che un indice multi-dimensionata utilizzata con l' in operatore viene parentesi La. In operatore che, non deve causare un tale elemento di esistere prove per l'esistenza di un particolare elemento di matrice Qualunque. un altro riferimento a un elemento di matrice inesistente lo creerà automaticamente. " Può essere trovato scorrendo un paragrafo o due verso l'alto da qui .
jw013,

1
Finché file1non è enorme (per un certo valore di enorme), preferirei questa soluzione in quanto non richiede alcun ordinamento file2e ci si aspetta che sia molto più efficiente.
jw013,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.