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

Каков наилучший способ сделать это? Это можно сделать в одну строку?

75 голосов | спросил Christian 25 Jpm1000000pmTue, 25 Jan 2011 18:28:35 +030011 2011, 18:28:35

14 ответов


0

Вы можете использовать:

grep -l Dansk * | xargs grep -l Norsk | xargs grep -l Svenska

Если вы также хотите найти в скрытых файлах:

grep -l Dansk .* | xargs grep -l Norsk | xargs grep -l Svenska
ответил vmpstr 25 Jpm1000000pmTue, 25 Jan 2011 18:44:17 +030011 2011, 18:44:17
0

Еще один способ, использующий только bash и grep:

Для одного файла 'test.txt':

  grep -q Dansk test.txt & grep -q Norsk test.txt & grep -l Svenska test.txt

Напечатает test.txt, если файл содержит все три (в любой комбинации). Первые два greps ничего не печатают (-q), а последние печатают файл, только если два других прошли. >

Если вы хотите сделать это для каждого файла в каталоге:

   для f в *; do grep -q Dansk $ f & & grep -q Norsk $ f & & grep -l Svenska $ f; сделанный
ответил Edd Steel 25 Jpm1000000pmTue, 25 Jan 2011 18:54:30 +030011 2011, 18:54:30
0
grep –irl word1 * | grep –il word2 `cat -` | grep –il word3 `cat -`
  • -i делает поиск нечувствительным к регистру
  • -r делает поиск файлов рекурсивным по папкам
  • -l соединяет список файлов с найденным словом
  • cat - заставляет следующий grep просматривать файлы, переданные в этот список.
ответил Gerry 13 Maypm13 2013, 23:30:39
0

Как выполнить поиск нескольких строк в файле на разных строках (используйте символ канала):

for file in *;do 
   test $(grep -E 'Dansk|Norsk|Svenska' $file | wc -l) -ge 3 && echo $file
done

Примечания:

  1. Если вы используете двойные кавычки "" со своим grep, вам придется выйти из канала следующим образом: \| для поиска Данска, Норска и Свенски.

  2. Предполагается, что в одной строке только один язык.

Пошаговое руководство: http: //www.cyberciti .biz /FAQ /HOWTO потребительной Grep-команда-в-Linux-Unix /

ответил Damodharan R 25 Jpm1000000pmTue, 25 Jan 2011 18:35:35 +030011 2011, 18:35:35
0

Вы можете сделать это очень легко с помощью ack :

ack -l 'cats' | ack -xl 'dogs'
  • -l: вернуть список файлов
  • -x: взять файлы из STDIN (предыдущий поиск) и искать только эти файлы

И вы можете просто продолжать пускать трубку, пока не получите только те файлы, которые вам нужны.

ответил Ben Johnson 19 ThuEurope/Moscow2013-12-19T19:50:18+04:00Europe/Moscow12bEurope/MoscowThu, 19 Dec 2013 19:50:18 +0400 2013, 19:50:18
0

Поиск нескольких слов в нескольких файлах:

egrep 'abc|xyz' file1 file2 ..filen 
ответил Sarath Chandra 15 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 15 Sep 2017 15:35:28 +0300 2017, 15:35:28
0
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
ответил kurumi 25 Jpm1000000pmTue, 25 Jan 2011 18:45:04 +030011 2011, 18:45:04
0

Просто:

grep 'word1\|word2\|word3' *

см. этот пост для получения дополнительной информации

ответил moshe beeri 17 PMpSun, 17 Apr 2016 16:46:04 +030046Sunday 2016, 16:46:04
0

Это сочетание ответов Гленна Джекмана и Куруми, которое допускает произвольное количество регулярных выражений вместо произвольного числа фиксированных слов или фиксированного набора регулярных выражений.

#!/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
ответил Dennis Williamson 25 Jpm1000000pmTue, 25 Jan 2011 23:01:25 +030011 2011, 23:01:25
0

В качестве дополнения к ответу awk @ kurumi приведем функцию 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
        }
    ' "[email protected]"
    return $?
}

Использование:

if all_word_search Dansk Norsk Svenska filename; then
    echo "all words found"
else
    echo "not all words found"
fi
ответил glenn jackman 25 Jpm1000000pmTue, 25 Jan 2011 19:52:36 +030011 2011, 19:52:36
0

Вот что хорошо сработало для меня:

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
ответил Nick Henry 27 +04002011-10-27T21:52:40+04:00312011bEurope/MoscowThu, 27 Oct 2011 21:52:40 +0400 2011, 21:52:40
0

Я сделал это в два этапа. Составьте список 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`

он сделал именно то, что мне было нужно - напечатать имена файлов, содержащие все три слова.

Также обратите внимание на такие символы, как `' "

ответил Simas 15 PM00000010000001731 2012, 13:58:17
0

Если вам нужны только два поисковых запроса, возможно, наиболее читаемый подход - запускать каждый поиск и пересекать результаты:

 comm -12 <(grep -rl word1 . | sort) <(grep -rl word2 . | sort)
ответил Ankur Dave 16 J000000Tuesday13 2013, 21:35:47
0

У меня была эта проблема сегодня, и все однострочники не помогли мне, потому что файлы содержали пробелы в именах.

Вот что я придумал, чтобы сработало:

grep -ril <WORD1> | sed 's/.*/"&"/' | xargs grep -il <WORD2>
ответил giusti 19 PMpTue, 19 Apr 2016 17:21:53 +030021Tuesday 2016, 17:21:53

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132