Chcę grep dla plików zawierających słowa Dansk
, Svenska
czy Norsk
na każdej linii, z użytkowym returnCode (jak ja naprawdę tylko jak mieć informacje, które zawarte są struny, mój jeden-liner idzie trochę dalej niż teraz).
Mam wiele plików z takimi liniami:
Disc Title: unknown
Title: 01, Length: 01:33:37.000 Chapters: 33, Cells: 31, Audio streams: 04, Subpictures: 20
Subtitle: 01, Language: ar - Arabic, Content: Undefined, Stream id: 0x20,
Subtitle: 02, Language: bg - Bulgarian, Content: Undefined, Stream id: 0x21,
Subtitle: 03, Language: cs - Czech, Content: Undefined, Stream id: 0x22,
Subtitle: 04, Language: da - Dansk, Content: Undefined, Stream id: 0x23,
Subtitle: 05, Language: de - Deutsch, Content: Undefined, Stream id: 0x24,
(...)
Oto pseudokod tego, czego chcę:
for all files in directory;
if file contains "Dansk" AND "Norsk" AND "Svenska" then
then echo the filename
end
Jaki jest najlepszy sposób, aby to zrobić? Czy można to zrobić w jednej linii?
PIPESTATUS
tablica zawiera wartości wyjściowe elementów potoku.pipefail
opcji powłoki (tymczasowo):shopt -so pipefail
grep -Z
ixargs -0
jeśli twoje nazwy plików mogą zawierać spacje.Jeszcze inny sposób używania tylko bash i grep:
Dla pojedynczego pliku „test.txt”:
Zostanie wydrukowane,
test.txt
jeśli plik zawiera wszystkie trzy (w dowolnej kombinacji). Pierwsze dwa polecenia greps niczego nie drukują (-q
), a ostatni drukuje plik tylko wtedy, gdy pozostałe dwa przeszły pomyślnie.Jeśli chcesz to zrobić dla każdego pliku w katalogu:
źródło
for f ...
: use"$f"
(podwójne cudzysłowy), a nie tylko$f
po to, aby upewnić się, że nazwy plików z osadzonymi spacjami itp. są poprawnie obsługiwane.-i
sprawia, że wielkość liter w wyszukiwaniu jest niewrażliwa-r
powoduje, że wyszukiwanie plików jest cykliczne w folderach-l
potokuje listę plików ze znalezionym słowemcat -
powoduje, że następny grep przejrzy listę plików przekazanych do niego.źródło
Jak grepować wiele ciągów w pliku w różnych liniach (użyj symbolu potoku):
for file in *;do test $(grep -E 'Dansk|Norsk|Svenska' $file | wc -l) -ge 3 && echo $file done
Uwagi:
Jeśli użyjesz podwójnych cudzysłowów
""
z grepem, będziesz musiał uciec od potoku w ten sposób:\|
aby wyszukać Dansk, Norsk i Svenska.Zakłada, że jedna linia ma tylko jeden język.
Przewodnik: http://www.cyberciti.biz/faq/howto-use-grep-command-in-linux-unix/
źródło
Norsk
, ale w trzech różnych wierszach.Możesz to zrobić naprawdę łatwo za pomocą potwierdzenia :
ack -l 'cats' | ack -xl 'dogs'
-l
: zwraca listę plików-x
: weź pliki z STDIN (poprzednie wyszukiwanie) i przeszukaj tylko te plikiMożesz po prostu kontynuować pracę, aż uzyskasz tylko te pliki, które chcesz.
źródło
Unknown option: x
. Czy istnieje wersja Ack, która obsługuje tę flagę x?awk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print "0" }'
możesz następnie złapać wartość zwracaną za pomocą powłoki
jeśli masz Ruby (1,9+)
ruby -0777 -ne 'print if /Dansk/ and /Norsk/ and /Svenka/' file
źródło
if (a && b && c) {exit 0} else {exit 1}
lub bardziej zwięźleexit !(a && b && c)
To wyszukuje wiele słów w wielu plikach:
egrep 'abc|xyz' file1 file2 ..filen
źródło
Po prostu:
grep 'word1\|word2\|word3' *
zobacz ten post, aby uzyskać więcej informacji
źródło
-l
flagę, ale poza tym ta odpowiedź wydaje mi się najprostsza, chyba że czegoś brakuje.Jest to połączenie odpowiedzi Glenna Jackmana i Kurumi, co pozwala na użycie dowolnej liczby wyrażeń regularnych zamiast dowolnej liczby ustalonych słów lub ustalonego zestawu wyrażeń regularnych.
#!/usr/bin/awk -f # by Dennis Williamson - 2011-01-25 BEGIN { for (i=ARGC-2; i>=1; i--) { patterns[ARGV[i]] = 0; delete ARGV[i]; } } { for (p in patterns) if ($0 ~ p) matches[p] = 1 # print # the matching line could be printed } END { for (p in patterns) { if (matches[p] != 1) exit 1 } }
Uruchom to w ten sposób:
./multigrep.awk Dansk Norsk Svenska 'Language: .. - A.*c' dvdfile.dat
źródło
Oto, co działało dobrze dla mnie:
find . -path '*/.svn' -prune -o -type f -exec gawk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print FILENAME }' {} \; ./path/to/file1.sh ./another/path/to/file2.txt ./blah/foo.php
Gdybym tylko chciał znaleźć pliki .sh z tymi trzema, mógłbym użyć:
find . -path '*/.svn' -prune -o -type f -name "*.sh" -exec gawk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print FILENAME }' {} \; ./path/to/file1.sh
źródło
Rozwijając odpowiedź awk @ kurumi, oto funkcja bash:
all_word_search() { gawk ' BEGIN { for (i=ARGC-2; i>=1; i--) { search_terms[ARGV[i]] = 0; ARGV[i] = ARGV[i+1]; delete ARGV[i+1]; } } { for (i=1;i<=NF; i++) if ($i in search_terms) search_terms[$1] = 1 } END { for (word in search_terms) if (search_terms[word] == 0) exit 1 } ' "$@" return $? }
Stosowanie:
if all_word_search Dansk Norsk Svenska filename; then echo "all words found" else echo "not all words found" fi
źródło
Zrobiłem to w dwóch krokach. Zrób listę plików csv w jednym pliku Z pomocą komentarzy na tej stronie wykonałem dwa kroki bez użycia skryptów, aby uzyskać to, czego potrzebowałem. Po prostu wpisz w terminalu:
$ find /csv/file/dir -name '*.csv' > csv_list.txt $ grep -q Svenska `cat csv_list.txt` && grep -q Norsk `cat csv_list.txt` && grep -l Dansk `cat csv_list.txt`
zrobił dokładnie to, czego potrzebowałem - wydrukował nazwy plików zawierające wszystkie trzy słowa.
Zwróć także uwagę na symbole, takie jak
`' "
źródło
Jeśli potrzebujesz tylko dwóch wyszukiwanych haseł, prawdopodobnie najbardziej czytelnym podejściem jest przeprowadzenie każdego wyszukiwania i przecięcie wyników:
źródło
Jeśli masz zainstalowany program git
--No-index przeszukuje pliki w bieżącym katalogu, który nie jest zarządzany przez Git. Więc to polecenie będzie działać w każdym katalogu, niezależnie od tego, czy jest to repozytorium git, czy nie.
źródło
Miałem dzisiaj ten problem, a wszystkie jednolinijkowe tutaj zawiodły mnie, ponieważ pliki zawierały spacje w nazwach.
Oto, co wymyśliłem, że zadziałało:
grep -ril <WORD1> | sed 's/.*/"&"/' | xargs grep -il <WORD2>
źródło