Bash: чи існує спосіб пошуку певного рядка в каталозі файлів? [дублікат]


47

Можливий дублікат:
пошук тексту тексту в Linux

В bash, мені було цікаво, чи існують команди, які дозволять вам знати, чи існує певна рядок, яку ви шукаєте, у файлах, розташованих у поточному каталозі, в якому ви перебуваєте.

Скажімо, ви шукаєте функцію "toUpperCase ()" у наборі файлів C у вашому поточному каталозі. Файлів дуже багато, тому ви не хочете вручну відкривати кожен з них за допомогою vim і перевіряти наявність рядка "toUpperCase", оскільки це зайняло б багато часу. Якщо не командний рядок bash, чи є інший спосіб зробити це ефективно?

Відповіді:


64

З grep:

grep -R "toUppercase()" *

Або якщо у вас встановлено Ack-grep , просто:

ack-grep "toUppercase"

Якщо ви хочете обмежити пошук у файлах C, ack-grepвиконайте такі дії:

ack-grep -cc "toUppercase()"

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


Настільки, що SO вже має підозріло подібне питання ;)
Девід Перрі

10

Стандартним інструментом пошуку тексту є греп .

Щоб шукати рядок toUpperCase(у всіх .cфайлах у поточному каталозі:

grep -F 'toUpperCase(' *.c

Якщо ви також хочете заглянути в підкаталоги:

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

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


ctagsкорисний для пошуку визначень функцій , а не викликів функцій .
JdeBP

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), записує місця, де виникають збіги, а потім вивантажує файл.


2

Так, інструмент називається grep.

Команда grep шукає один або кілька вхідних файлів для рядків, що містять відповідність заданому шаблону. За замовчуванням grep друкує відповідні рядки.

Основне використання:

grep something somewhere

Або, більш конкретно:

grep [some options] pattern file

У дуже простому випадку ви хочете рекурсивно шукати всі файли, таким чином ви надаєте -rможливість. Якщо вам не байдуже великі чи малі регістри, зробіть це невідчутливим до регістру за допомогою цього -iпараметра.

grep -ri "touppercase()" .

Якщо ви хочете лише відповідні частини, скористайтеся -oопцією.

Греп може використовувати регулярні вирази , і він має величезний посібник .


2

grepстандартна відповідь - використовуючи прапор -r для пошуку рекурсивно або спільно з find(обговорення та приклади в інших питаннях на цьому веб-сайті, наприклад, на цьому )

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


1

find і grep

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

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

grep -r string .буде повторюватися через весь файл у поточному каталозі. Якщо у вас є об'єктивні файли або інші двійкові файли, ви можете отримати збіг із двійковими результатами. мотлох. Якщо у вашому підкаталозі також є файли fifos або пристроїв, у вас можуть бути невідомі / ненавмисні наслідки.

grep string *.cшукає лише поточні .cфайли каталогів .

grep string **/*.c здійснює пошук у всіх підкаталогах. Однак якщо у вас дуже велика кількість .cфайлів, ви ризикуєте перевищити максимальну кількість розширень для глобальної оболонки. Розширення також має відбутися спочатку, що означає повний обхід дерева перед його 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

3
grep має -H варіант, який робить це вже. grep -Hn what what *
Рой Ріко

Щодня дізнайтеся щось нове. Дякую @Roy Rico
Тім Брігхем,

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"

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

дуг

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.