40

Возможный дубликат:
Поиск текстового шаблона в Linux

В bash мне было интересно, есть ли какие-нибудь команды, которые позволят вам узнать, существует ли конкретная искомая строка в файлах, находящихся в текущем каталоге, в котором вы находитесь.

Допустим, вы ищете функцию toUpperCase() в наборе файлов C в вашем текущем каталоге. Существует множество файлов, поэтому вам не нужно открывать каждый вручную с помощью vim и проверять строку «toUpperCase», потому что это займет много времени. Если нет командной строки bash, есть ли другой способ сделать это эффективно?

8 ответов8

57

С grep:

grep -R "toUppercase()" *

Или, если у вас установлен ack-grep , просто:

ack-grep "toUppercase"

Если вы хотите ограничить поиск в файлах C, используйте ack-grep:

ack-grep -cc "toUppercase()"

ack-grep также может быть установлен на OSX, но исполняемый файл называется просто ack .

9

Стандартный инструмент поиска текста - grep.

Чтобы найти строку toUpperCase( во всех файлах .c в текущем каталоге:

grep -F 'toUpperCase(' *.c

Если вы хотите посмотреть и в подкаталогах:

grep -r --include='*.c' -F 'toUpperCase('

Если вы ищете вызовы функций C, тогда ctags может подойти лучше. Вы запускаете его один раз для всех своих исходных файлов, чтобы создать индекс идентификаторов, а затем используете свой редактор для навигации между вызовами. Все редакторы, похожие на vi, могут использовать файл TAGS ctags. Если вы используете Emacs, запустите аналогичную программу etags .

6

Вы используете Vim. У вас есть инструмент, чтобы сделать это встроенным.

Как и ожидалось, уже есть семь ответов, в которых говорится, что нужно использовать grep . Но я, кажется, пока единственный человек, который заметил из вашего вопроса, что вы используете vim . Таким образом, хотя вы можете использовать grep изнутри vim , вы также можете использовать встроенный инструмент vim . Это вызывается с помощью команды :vimgrep .

Чтобы выполнить поиск «всех исходных файлов C в текущем каталоге для вызовов функции toUpperCase() », введите команду vim

:vimgrep "\<toUpperCase\_s*(" *.c

Результирующий список совпадений автоматически загружается в список быстрых исправлений, доступный любому из них (см. Интерактивную справку для тонкой разницы)

:copen
:cwin

Чтобы найти определение функции, а не вызовы к ней, ctags является инструментом, как упомянуто в ответе Gilles, в сочетании с :tjump или :tselect .

Зачем использовать :vimgrep?

Онлайновая справка (:help grep) перечисляет несколько причин, которые я не буду здесь описывать. В дополнение к этому, сравните действие :vimgrep с dietbuddha. dietbuddha разветвляет отдельный процесс grep для каждого отдельного исходного файла C. Он даже не использует xargs чтобы уменьшить эти накладные расходы. И вам все равно придется как-то анализировать выходные данные, чтобы вызвать ваш текстовый редактор в соответствующих исходных файлах после его завершения. :vimgrep вообще не отключает несколько дополнительных процессов, а использование результата само по себе просто. При простом выборе одной из записей в результирующем списке быстрых исправлений курсор автоматически помещается на соответствующую строку соответствующего исходного файла.

На самом деле, он делает именно то, что вы написали, вы бы делали вручную, кроме как автоматически. Это автоматизированный способ выполнения тех же самых действий текстового редактора. Он загружает файл, как если бы он был загружен вручную, ищет в нем регулярное выражение (используя тот же синтаксис регулярного выражения, который вы уже использовали в другом месте в vim), записывает места, где происходят совпадения, и затем выгружает файл.

3

Да, инструмент называется grep.

Команда grep ищет в одном или нескольких входных файлах строки, содержащие соответствие указанному шаблону. По умолчанию grep печатает совпадающие строки.

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

grep something somewhere

Или, более конкретно:

grep [some options] pattern file

В очень простом случае вы рекурсивно хотите искать по всем файлам, поэтому вы предоставляете опцию -r . Если вам не нужны прописные или строчные буквы, сделайте их независимыми от регистра с опцией -i .

grep -ri "touppercase()" .

Если вам нужны только подходящие детали, используйте опцию -o .

Grep может использовать регулярные выражения, и у него есть огромное руководство.

2

grep является стандартным ответом - используется либо флаг -r для рекурсивного поиска, либо в сочетании с find (обсуждение и примеры в других вопросах на этом сайте, таких как этот)

Мой привилегированный выбор в последнее время ack Скорее всего, он не установлен на вашем компьютере, но вы можете установить его с помощью apt-get в Ubuntu или просто загрузить. Ссылки, инструкции и причины, по которым он лучше, чем grep, доступны по адресу http://betterthangrep.com/.

1

find и grep

find myproject -name '*.c' -exec grep 'toUpperCase(' {} \; -print

почему не только grep?

grep -r string . будет проходить через весь файл в текущем каталоге. Если у вас есть объектные файлы или другие двоичные файлы, вы можете получить совпадение с двоичными результатами, иначе. мусор. Если в вашем подкаталоге также есть файлы fifo или файлы устройств, это может привести к неизвестным / непреднамеренным последствиям.

grep string *.c ищет только текущие каталоги .c файлов.

grep string **/*.c выполняет поиск во всех подкаталогах. Однако, если у вас очень большое количество файлов .c вы рискуете превысить максимальное количество расширений для glob оболочки. Расширение также должно произойти в первую очередь, что означает полный обход дерева, прежде чем начнется grep .

0

Grep добьется цели, но немного дополнительных сценариев поможет найти имя файла и точную строку, на которую он ссылается. Если это то, что вы хотите, я считаю, что следующее работает хорошо. Я сохранил его как сценарий оболочки и передал ему нужное значение в качестве первого параметра командной строки.

for i in $(ls)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?
    if [ $STATUS  -eq 0 ] ; then
        echo $i
        cat $i | grep -n $1
    fi
done
0

Интересно, что никто не ответил на ваш конкретный вопрос: «Как мне найти, существует ли конкретная строка в файлах, находящихся в текущем каталоге». Насколько я знаю, нет никакой опции grep, которая только возвращает, было ли найдено совпадение в группе файлов. Ближайшая опция - это -l, чтобы вывести список имен файлов. Ближайший ответ среди тех, кто пока что дал Тим, с небольшими изменениями:

#!/usr/bin/bash

for i in $(ls *.c 2> /dev/null)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?

    if [ $STATUS  -eq 0 ] ; then
        echo "Found"
        exit
    fi
done

echo "Not found"

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

Дуг

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .