Найдите несколько шаблонов слова в файлах

У меня есть приблизительно 50 000 файлов (.txt) и больше объектов в filesdir папке. Значения: 'факс', 'телефон', 'адрес' представлен в различных конфигурациях в этих файлах. Я должен найти все файлы, которые содержат 'факс' И 'звонят', и не содержит 'адрес'. Я попробовал за цикл с несколькими командами grep. ls дает 'слишком много аргументов'. Таким образом, я попробовал:

find /filesdir/ -maxdepth 1 -name '*.txt' -exec grep -l 'fax' \; grep -l 'phone' \; grep -l -v 'address'

Почему это не работает?

0
задан 27 March 2018 в 08:00

4 ответа

Существует несколько причин, которые не работали бы:

  • Вы опустили {} заполнитель для -exec
  • Вы пытаетесь -exec несколько grep команды с единственным вызовом
  • Я подозреваю, что Ваша логика испорчена, так как операция по умолчанию для находки логична AND тогда как Вы, по-видимому, хотите fax ИЛИ phone И not address

Я не полностью протестировал его, но я думаю, что Вы хотите что-то больше как

find /filesdir/ -maxdepth 1 -name '*.txt' -exec grep -q 'fax\|phone' {} \; -exec grep -lv 'address' {} \;
1
ответ дан 30 October 2019 в 04:36

Печать имен файлов и их содержания на одной строке для каждого файла

Я думаю, что эта командная строка сделает это:

find -maxdepth 1 -name "*.txt" -exec echo "{} :" \; -exec cat {} \; -exec echo EOF \;| tr '\n' ' '|sed 's/EOF /\n/g'|grep -iv 'address'|grep -i 'fax'|grep -i 'phone'

Объяснение:

  • для каждого файла (который найден find)

    • повторите имя файла
    • распечатайте содержание
    • распечатайте флаг End Of File (который должен отличаться от того, что может быть в файлах. Выберите этот флаг тщательно! Я использую EOF, Вам, возможно, понадобится что-то еще.
  • для целого вывода

    • преобразуйте новые строки в пробелы для получения всего на одной строке
    • преобразуйте Конец флагов Файла к новым строкам

    Теперь содержание каждого файла находится в одной отдельной строке, подходящей для grep .

  • и наконец

    • пропустите строки с 'адресом'
    • от остающегося вывода выберите строки с 'факсом'
    • от остающегося вывода выберите строки с 'телефоном'

Печать только имен файлов

Предыдущая командная строка печатает имена файлов и содержание файла (объединенный с одной строкой), который хорош для тестирования, но не для обработки тысяч файлов.

Следующая командная строка печатает только имена файлов. Это использует ':::' для разделения каждого имени файла от содержания файла.

find -maxdepth 1 -name "*.txt" -exec echo "{} :::" \; -exec cat {} \; -exec echo EOF \;| tr '\n' ' '|sed 's/EOF /\n/g'|grep -iv 'address'|grep -i 'fax'|grep -i 'phone' | sed 's/ :::.*//'
1
ответ дан 30 October 2019 в 04:36

git grep

Можно использовать git grep для нескольких шаблонов, объединенных с помощью булевых выражений, например:

git grep --all-match --no-index -e "fax" --and -e "phone" --and --not -e "address"

Можно объединить различные шаблоны с булевыми выражениями такой как --and, --or и --not.

--all-match При предоставлении нескольких выражений шаблона этот флаг указан для ограничения соответствия файлами, которые имеют строки для соответствия всем им.

--no-index Поисковые файлы в текущем каталоге, которым не управляет Мерзавец.

-l/--files-with-matches/--name-only Покажите только названия файлов.

-e Следующий параметр является шаблоном. Значение по умолчанию должно использовать основной regexp.

Другие параметрические усилители для рассмотрения:

--threads Количество grep рабочих потоков для использования.

-q/--quiet/--silent Не производите подобранные строки; выход с состоянием 0, когда существует соответствие.

Для изменения типа шаблона можно также использовать -G/--basic-regexp (значение по умолчанию), -F/--fixed-strings, -E/--extended-regexp, -P/--perl-regexp, -f file, и другой.

Проверить man git-grep для дальнейшей справки.

grep

Вот grep синтаксис, который использует замены цепи инстанций:

grep -L "address" $(grep -l "phone" $(grep -rl "fax" .))

Объяснение:

  1. Найдите имена файлов, имеющие шаблон "факса" (grep -rl "fax" .).
  2. Отфильтруйте найденные имена файлов, которые имеют "телефонный" шаблон (grep -l "phone" $(cmd)).
  3. Отфильтруйте далее вниз для исключения файлов, не имеющих address (grep -L "address" $(cmd)).

Если Вы работаете с большими данными, рассматриваете использование ripgrep вместо этого.

find

Выше примера может не работать хорошо с файлами с пробелами, таким образом, вот версия с find:

find . -type f -name '*.txt' \
  -execdir bash -c 'grep -L "address" "$(grep -l "phone" "$(grep -l "fax" "{}")")"' ';' \
2>/dev/null

См. также: Проверьте, существуют ли все несколько строк или regexes в файле

2
ответ дан 30 October 2019 в 04:36

Для нахождения файлов (совместимыми с файлами включая пробельную/или новую строку), они не содержат шаблон address:

find -type f ! -exec grep -q 'address' {} \; -print 

и распечатайте только тех, который содержит шаблоны fax и phone в любом порядке в целом файле:

find -type f ! -exec grep -q 'address' {} \; \
               -exec grep -qP '(?s)(?=.*?fax)(?=.*?phone)' {} \; -print

Или POSIXly:

find -type f ! -exec grep -q 'address' {} \; \
               -exec grep -q 'fax' {} \; \
               -exec grep -q 'phone' {} \; -print

Или принятие там нет \newline на имя файлов, затем:

grep -lP '(?s)(?=.*?fax)(?=.*?phone)' * |xargs -d'\n' grep -L address
  • (?=pattern): Положительное Предвидение: положительная предварительная конструкция является парой круглых скобок, с вводной круглой скобкой, сопровождаемой вопросительным знаком и, равняется знаку.

  • (?s) Известная "точка - все", который говорит grep позволять точку . соответствовать \nсимволы ewline также.

  • .*? средства, соответствующие любым символам . то, что нуль случаев или больше раз * в то время как они дополнительные сопровождаемый шаблоном (fax или phone). ? делает все дополнительным перед ним (нуль средств или одно время всего подобранного .*)

будущее чтение:

Предвидение Regex, lookbehind и атомарные группы

1
ответ дан 30 October 2019 в 04:36

Другие вопросы по тегам:

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