Intereting Posts

Искать только в файлах, соответствующих шаблону с помощью ack

Может выполнять поиск только через файлы, соответствующие конкретному шаблону «glob» (например: поиск foo во всех файлах с именем «bar * .c»). Команда

ack foo "bar*.c" 

работает только в текущем каталоге.

Примечание. Я знаю, что это возможно при поиске -exec:

 find . -name "bar*.c" -type f -exec ack foo {} + 

Но мне нужна небольшая и простая команда ack, потому что find не пропускает каталоги управления версиями.

    Поиск каталогов

    Основываясь на синопсисе, показанном на странице руководства, я бы сказал, что он может обрабатывать каталог, но, глядя на переключатели, он не может искать только файл на основе шаблона. Для этого вам придется заручиться find . Команда ack включает в себя параметр --files-from=FILE чтобы он мог получать список файлов из find .

    конспект

      ack [options] PATTERN [FILE...] ack -f [options] [DIRECTORY...] 

    Применение

      --files-from=FILE The list of files to be searched is specified in FILE. The list of files are separated by newlines. If FILE is "-", the list is loaded from standard input. 

    Существует --ignore-file= которая может дать вам то, что вы хотите, но, по-видимому, немного больно на самом деле.

      --ignore-file=FILTERTYPE:FILTERARGS Ignore files matching FILTERTYPE:FILTERARGS. The filters are specified identically to file type filters as seen in "Defining your own types". 

    Поиск определенных типов файлов

    Единственный другой способ, который я могу себе представить, – это использовать его --type переключатель:

      --type=[no]TYPE Specify the types of files to include or exclude from a search. TYPE is a filetype, like perl or xml. --type=perl can also be specified as --perl, and --type=noperl can be done as --noperl. If a file is of both type "foo" and "bar", specifying --foo and --nobar will exclude the file, because an exclusion takes precedence over an inclusion. 

    Чтобы узнать, какие типы доступны:

     $ ack --help-types | grep -E "perl|cpp" 

    формат. Например, работают как -type = perl и -perl. – [нет] cpp .cpp .cc .cxx .m .hpp .hh .h .hxx – [no] objcpp .mm .h – [no] perl .pl .pm .pod .t .psgi; первая строка соответствует /^#!.*\bperl/ – [no] perltest .t

    Примеры

    Найдите все файлы Perl на основе как имени файла (* .pm, * .pl, * .t и * .pod), так и строки shebang.

     $ ack -f --type perl examples/iwatch/iwatch/iwatch examples/nytprof_perl/bad.pl 

    Найти все файлы на C ++:

     $ ack -f --type=cpp Shared/Scanner.h Shared/Sorter.h Shared/DicomHelper.cpp Shared/DicomDeviationWriter.h 

    Поиск foo в баре * .c

    Итак, как вы можете достичь того, чего хотите? Ну, вы, вероятно, будете использовать find для этого:

     $ find adir -iname "bar*.c" | ack --files-from=- foo adir/bar1.c 1:foo 2:foo adir/dir1/bar1.c 1:foo 2:foo 

    Вы также можете использовать возможность ack для поиска файлов, которые соответствуют заданному шаблону в именах файлов (с использованием -g <pattern> ), а затем передать этот список во второй вызов ack с помощью -x или --files-from=- ..

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

     $ ack -g '\bbar.*.c$' | ack -x foo bar1.c 1:foo 2:foo dir1/bar1.c 1:foo 2:foo 

    Использование -files-from=- :

     $ ack -g '\bbar.*.c$' | ack --files-from=- foo bar1.c 1:foo 2:foo dir1/bar1.c 1:foo 2:foo 

    В любом случае мы сопоставляем имена файлов, которые вы хотите использовать с этим регулярным выражением:

     \bbar.*.c$ 

    Это соответствует файлам с именем bar.*c и end после .c используя конец привязки строки, $ . Мы также должны убедиться, что имена имеют граничный символ, используя \b . Это приведет к сбою файлов, содержащих граничные символы, например, $bar.c или %bar.c

    Это легко, если тип файла известен, и ack знает много типов файлов. Поэтому, если вы хотите, например, искать только в файлах C, чем вы можете:

     ack --cc 'string' 

    Но если это не одно из известных расширений, вам нужно определить свой собственный тип. Это должно работать:

     ack --type-set barc:match:/bar.+\.c/ --barc 'string' 

    Обратите внимание, что вам нужны как -type-set, так и -barc.

    (Спасибо Энди, который также помог с этим в списке рассылки.)

    «Что нового в ack 2?» http://beyondgrep.com/ack-2.0/

    с ack 2.0 вы можете использовать новый -x для ввода имен файлов из одного вызова ack в другой.

     ack2 -g -i filepattern | ack2 -x -w searchpattern 

    Только я не могу заставить его работать:

     % ack -g "*bar*.c" Invalid regex '*bar*.c': Quantifier follows nothing in regex; marked by <-- HERE in m/* <-- HERE bar*.c/ at ack line 314. 

    Таким образом, кажется, что -g нуждается в регулярном выражении, в то время как я хочу вариант «glob» style …

    Вы хотите только определенный шаблон или просто хотите исходные файлы C?

    Если вы хотите все файлы C, используйте

     ack --cc foo 

    Если вы хотите, чтобы все файлы C и файлы заголовков NOT C использовали

     ack --cc --no-hh foo 

    Ack не поддерживает выбор файла стиля glob. Поскольку я действительно пропустил это, я создал небольшой скрипт оболочки ackg :

     #!/bin/sh # 'glob' support for ack find -name "$2" -type f -exec ack "$1" {} + 

    Теперь вы можете использовать команду:

     ackg foo "bar*.c" 

    Но обратите внимание: это, к сожалению, также будет искать в версиях управления версиями (например: .git).

    Это можно сделать с помощью опции -G для ag, серебряного искателя (расширенный клон ack-grep).

     $ echo foo > bar_wanted.c $ echo foo > unwanted.c $ ag -G "bar.*\.c" foo bar_wanted.c 1:foo 

    Заметки:

    • ag использует синтаксис регулярных выражений PCRE , поэтому regexp должен быть bar.*\.c вместо bar*.c .
    • Опция -G должна предшествовать поисковому запросу, так как все, что после этого интерпретируется как имя файла.

    Это казалось бы самым быстрым и безопасным:

     find . -name '*.c' | ack -x 'some string' 

    -x Прочитать список файлов для поиска из STDIN.

    Однако, если файл, вероятно, будет находиться в вашей базе данных locate , это будет еще быстрее:

     locate --basename '*.c' | ack -x 'some thing' 

    Locate также может принимать регулярные выражения старой школы, немного болезненные, но если вы ищете c файлы, это может потребоваться. например

     locate --basename --regexp '\.\(c\|cpp\|h\|hpp\|cc\)$' | ack -x 'some thing' 

    Это просто переводится на: «искать все имена файлов, которые заканчиваются на c, cpp, h, hpp или cc».

    Используя zsh, вы можете:

     ls **/a*.txt | ack --files-from=- something