„Ungrep” - które wzory nie są dopasowane

13

Szukam polecenia lub skryptu, aby wykonać następujące czynności - dane:

plik1.txt:

abcd
efgh 
ijkl
mnop

plik2.txt:

123abcd123
123efgh123
123mnop123

Chcę polecenia, które robi coś takiego:

ungrep file1.txt file2.txt

i zwraca:

ijkl

Innymi słowy, daje mi wiersze w pliku1.txt, które nie zwrócą żadnych wyników dla grep pliku2.txt. Wiem, że mogę to zrobić, wykonując iterację przez plik1.txt, grepping file2.txt dla każdej linii i zapisując wynik, i wypisując dowolne linie, w których wynik jest pusty, ale liczyłem na bardziej skuteczny sposób, aby to zrobić.

Edward Shtern
źródło

Odpowiedzi:

18

W GNU greppowinny działać następujące elementy. Korzystając z -fopcji, przekaż file1.txtjako „plik sygnatur” - ale przekaż go po raz drugi jako plik danych. Służy -odo zgłaszania tylko pasujących części. Na koniec wyodrębnia słowa, które pasują tylko raz - odpowiadają one wierszom file1.txt, w których nie znaleziono dopasowania file2.txt.

grep -h -o -f  file1.txt file2.txt file1.txt | sort | uniq -u
ijkl
iruvar
źródło
Bardzo dobry opis. Dzięki i +1.
unxnut
4
Możesz osiągnąć ten sam efekt bez podstępu grep: sort file1.txt <(grep -of file1.txt file2.txt) | uniq -uale, podobnie jak twoje rozwiązanie, działa to tylko wtedy, gdy plik wzorca nie zawiera żadnych metaznaków wyrażeń regularnych.
rici
@rici, to bardzo dobra uwaga
iruvar,
2
Poprawa:grep -oFf file1.txt file2.txt | sort file1.txt - | uniq -u
Stéphane Chazelas,
10

Możesz to zrobić za pomocą awk:

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

Używając index, szukamy podciągów zamiast dopasowywania wyrażeń regularnych.

Ponieważ usuwamy słowo z tablicy, gdy tylko znajdziemy dopasowanie, unikamy niepotrzebnych wyszukiwań.

Stéphane Chazelas
źródło
1
Zaakceptowałbym tylko ten. Nie wywołuje żadnego sortowania O (n log n) i nie zawiedzie się dziwnie, gdy wzorce zawierają metaznaki wyrażeń regularnych, i można je rozszerzyć o obsługę wyrażeń regularnych.
Kaz
Nie mogę uwierzyć, że w[$0]sama ocena ma efekt uboczny dodania klucza do tablicy.
Kaz
1
@Kaz, tak, to może być mylące, a wiele skryptów nie świadomie alokuje elementów tablicy przez przypadek, robiąc if (a[$1])zamiast, if ($1 in a)na przykład. To sprawa każdego awkw tym oryginalna awki nawk, ale patrząc na standardowym wczoraj, nie mogłem znaleźć to określone.
Stéphane Chazelas,
1
@Kaz Oto cytat z POSIX: „Aplikacja powinna zapewnić, że indeks wielowymiarowy używany z operatorem in jest nawiasowany. Operator in , który sprawdza istnienie określonego elementu tablicy, nie spowoduje, że element ten istnieje. inne odniesienie do nieistniejącego elementu tablicy automatycznie go utworzy. ” Można go znaleźć, przewijając akapit lub dwa stąd .
jw013,
1
Tak długo, jak długo file1nie jest ogromny (dla pewnej wartości ogromnej), wolę to rozwiązanie, ponieważ nie wymaga żadnego sortowania file2i oczekuje się, że będzie znacznie bardziej wydajne.
jw013,