Я хочу использовать grep для файлов, содержащих слова Dansk
, Svenska
или Norsk
в любой строке с пригодным для использования кодом возврата (поскольку мне действительно нравится только информация, содержащаяся в строках, мой однострочник идет немного дальше этого).
У меня много файлов с такими строками:
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,
(...)
Вот псевдокод того, что я хочу:
for all files in directory;
if file contains "Dansk" AND "Norsk" AND "Svenska" then
then echo the filename
end
Как лучше всего это сделать? Можно ли это сделать в одной строке?
PIPESTATUS
массив содержит значения выхода членов конвейера.pipefail
опцию оболочки (временно):shopt -so pipefail
grep -Z
и,xargs -0
если ваши имена файлов могут содержать пробелы.Еще один способ с использованием только bash и grep:
Для одного файла test.txt:
Напечатает,
test.txt
если файл содержит все три (в любой комбинации). Первые два grep ничего не печатают (-q
), а последний выводит файл только в том случае, если два других прошли.Если вы хотите сделать это для каждого файла в каталоге:
источник
for f ...
: используйте"$f"
(двойные кавычки), а не просто$f
для того, чтобы имена файлов со встроенными пробелами и т. д. обрабатывались правильно.-i
делает поиск нечувствительным к регистру-r
делает рекурсивный поиск файлов по папкам-l
прокручивает список файлов словом найденоcat -
заставляет следующую команду grep просматривать переданные ему файлы.источник
Как выполнить grep для нескольких строк в файле на разных строках (используйте символ вертикальной черты):
for file in *;do test $(grep -E 'Dansk|Norsk|Svenska' $file | wc -l) -ge 3 && echo $file done
Ноты:
Если вы используете двойные кавычки
""
с вашим grep, вам придется избегать конвейера следующим образом:\|
искать Dansk, Norsk и Svenska.Предполагает, что в одной строке только один язык.
Пошаговое руководство: http://www.cyberciti.biz/faq/howto-use-grep-command-in-linux-unix/
источник
Norsk
, но в трех разных строках.Вы можете сделать это очень легко с помощью ack :
ack -l 'cats' | ack -xl 'dogs'
-l
: вернуть список файлов-x
: взять файлы из STDIN (предыдущий поиск) и искать только эти файлыИ вы можете просто продолжать работу, пока не получите только те файлы, которые вам нужны.
источник
Unknown option: x
. Есть ли какая-то версия ack, которая поддерживает этот флаг x?awk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print "0" }'
затем вы можете поймать возвращаемое значение с помощью оболочки
если у вас Ruby (1.9+)
ruby -0777 -ne 'print if /Dansk/ and /Norsk/ and /Svenka/' file
источник
if (a && b && c) {exit 0} else {exit 1}
или корочеexit !(a && b && c)
Это ищет несколько слов в нескольких файлах:
egrep 'abc|xyz' file1 file2 ..filen
источник
Просто:
grep 'word1\|word2\|word3' *
см. этот пост для получения дополнительной информации
источник
-l
флаг, но кроме этого, этот ответ кажется мне наиболее простым, если я чего-то не упускаю.Это смесь ответов Гленна Джекмана и Куруми, которая позволяет использовать произвольное количество регулярных выражений вместо произвольного количества фиксированных слов или фиксированного набора регулярных выражений.
#!/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 } }
Запускаем так:
./multigrep.awk Dansk Norsk Svenska 'Language: .. - A.*c' dvdfile.dat
источник
Вот что мне понравилось:
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
Если бы я просто хотел найти файлы .sh с этими тремя, я мог бы использовать:
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
источник
Расширяя ответ @kurumi awk, вот функция 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 $? }
Применение:
if all_word_search Dansk Norsk Svenska filename; then echo "all words found" else echo "not all words found" fi
источник
Я сделал это в два этапа. Составьте список файлов csv в одном файле. С помощью комментариев к этой странице я сделал два шага без скриптов, чтобы получить то, что мне нужно. Просто введите в терминал:
$ 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`
он сделал именно то, что мне нужно - распечатал имена файлов, содержащие все три слова.
Также обратите внимание на символы вроде
`' "
источник
Если вам нужны только два условия поиска, возможно, наиболее читаемый подход - запускать каждый поиск и пересекать результаты:
источник
Если у вас установлен git
Параметр --no-index ищет файлы в текущем каталоге, которым не управляет Git. Таким образом, эта команда будет работать в любом каталоге, независимо от того, является ли он репозиторием git или нет.
источник
У меня была эта проблема сегодня, и все однострочные здесь не помогли мне, потому что файлы содержали пробелы в именах.
Вот что я придумал, что сработало:
grep -ril <WORD1> | sed 's/.*/"&"/' | xargs grep -il <WORD2>
источник