Użyj listy słów, aby grep na innej liście

8

Mam listę z 250 liniami. Muszę uruchomić je wszystkie przez serwer WWW, aby uzyskać listę wyników. Ta lista zwraca jednak o wiele więcej wierszy, niż jestem zainteresowany. Powiedzmy, że moje list.txtto:

a.1
b.1
etc

następnie dane wyjściowe to output.txt:

a.1 a b c
a.2 b a b
a.3 d k o
b.1 b o p
b.2 o i y
b.3 p i y
etc

Czy można użyć polecenia grep, aby wyszukać wszystkie słowa w list.txt w pliku output.txt, a następnie wygenerować listę „Wanted” Want.txt? Potrzebuję całego wiersza w moim pliku wyjściowym. Txt Jestem nowy w skryptach, ale chciałbym coś takiego

grep list.txt output.txt > wanted.txt

Nie znalazłem żadnych przykładów tego

Ditte
źródło
Czy oba są w kolejności alfabetycznej jak twoje przykłady?
Oli
Nie, mam określoną kolejność niealfabetyczną na liście.txt, ale plik output.txt jest alfabetyczny, ale chciałbym, aby zawierał tylko „trafienia” dla mojej listy.txt w tej samej kolejności niealfabetycznej
Ditte

Odpowiedzi:

11

Zignorowałbym grepten. Jest dobry do wyrażeń regularnych, ale nie wygląda na to, że naprawdę potrzebujesz go tutaj. commmoże porównać dwa pliki i pokazać skrzyżowania. Korzystając z dokładnych przykładów:

$ comm -12 list.txt output.txt 
a.1
b.1
etc

Jest to szybsze niż jakikolwiek grep, ale zależy (w dużym stopniu) od sortowanych plików. Jeśli nie są, możesz je wstępnie posortować, ale to zmieni dane wyjściowe, więc również zostanie posortowane.

comm -12 <(sort list.txt) <(sort output.txt) 

Alternatywnie, ta odpowiedź od iiSeymour pozwoli ci to zrobić grep. Flagi proszą o plik wejściowy i wymuszają wyszukiwanie ciągów pełnych słów. To nie będzie zależało od zamówienia, ale będzie oparte na output.txtzamówieniu. Odwróć pliki, jeśli chcesz je w kolejności list.txt.

$ grep -wFf list.txt output.txt 
a.1
b.1
etc

Jeśli twój list.txtjest naprawdę duży, być może będziesz musiał poradzić sobie z tym trochę iteracyjnie i przekazać każdą linię osobno. To znacznie wydłuży czas przetwarzania. W powyższym output.txtczytałbyś raz, ale w ten sposób czytałeś i przetwarzałeś go dla każdej linii list.txt. To okropne ... Ale to może być twój jedyny wybór. Z drugiej strony sortuje rzeczy według list.txtkolejności.

$ while read line; do grep -wF "$line" output.txt; done < list.txt
a.1
b.1
etc
Oli
źródło
1
To jest naprawdę mądre! Jaki jest powód -12?
Ditte
3
-1pomija wiersze unikalne dla pierwszego pliku, -2pomija wiersze unikalne dla drugiego pliku i -3pomija wiersze wspólne dla obu plików . Aby uzyskać tylko wspólne linie, tłumimy unikalne, stąd -12.
Oli
miły! Myślę, że użyję komendy comm. A kiedy chcę posortować plik output.txt, aby mieć taką samą kolejność jak list.txt, użyję po prostu comm -12 <(sort list.txt) <(sort output.txt)?
Ditte
Komenda comm nie dała mi całej linii w wynikach.txt (i potrzebuję tego wszystkiego, aby uzyskać stamtąd informacje). Ale jeśli spróbuję polecenia grep, to daje mi grep: brak pamięci. Czy to znaczy, że jest za duży?
Ditte
drugi przykład zawiera redundantne przekierowanie STDIN, powłoka oznaczałaby jako błąd. albo stwórz pliki tymczasowe, albo użyj dodatkowego fd z potokowym sortowaniem w tle (trudne w większości powłok) ... to bardziej pytanie programistyczne, które lepiej zadać w przypadku przepełnienia stosu . osobiście zrobiłbym to w Pythonie.
Skaperen