Bash: czy istnieje sposób wyszukiwania określonego ciągu w katalogu plików? [duplikować]

47

Możliwa duplikat:
Wyszukaj wzór tekstowy w systemie Linux

W bashie zastanawiałem się, czy istnieją jakieś polecenia, które poinformują cię, czy określony ciąg znaków istnieje w plikach znajdujących się w bieżącym katalogu, w którym się znajdujesz.

Załóżmy, że szukasz funkcji „toUpperCase ()” w zestawie plików C w bieżącym katalogu. Istnieje wiele plików, więc nie chcesz ręcznie otwierać każdego z nich za pomocą vima i sprawdzać łańcucha „toUpperCase”, ponieważ zajęłoby to dużo czasu. Jeśli nie jest to linia poleceń bash, czy istnieje inna metoda, aby zrobić to skutecznie?

Mroczny Templariusz
źródło

Odpowiedzi:

64

Z grep:

grep -R "toUppercase()" *

Lub, jeśli masz zainstalowany ack-grep , po prostu:

ack-grep "toUppercase"

Jeśli chcesz ograniczyć wyszukiwanie w plikach C, za pomocą ack-grep:

ack-grep -cc "toUppercase()"

ack-grepmożna również zainstalować na OSX, ale plik wykonywalny nazywa się po prostu ack.

Trasplazio Garzuglio
źródło
Do tego stopnia, że ​​SO ma już podejrzanie podobne pytanie ;)
David Perry, 10.10
10

Standardowym narzędziem wyszukiwania tekstu jest grep .

Aby wyszukać ciąg toUpperCase(we wszystkich .cplikach w bieżącym katalogu:

grep -F 'toUpperCase(' *.c

Jeśli chcesz również zajrzeć do podkatalogów:

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

Jeśli szukasz C wywołań funkcji, a następnie ctags może być lepsze dopasowanie. Uruchom go raz na wszystkich plikach źródłowych, aby utworzyć indeks identyfikatorów, a następnie użyj edytora do nawigacji między połączeniami. Wszystkie edytory podobne do vi mogą używać TAGSpliku ctags . Jeśli używasz Emacsa, uruchom podobny program etags.

Gilles „SO- przestań być zły”
źródło
ctagsjest przydatny do znajdowania definicji funkcji , a nie wywołań funkcji .
JdeBP
6

Używasz vima. Masz wbudowane narzędzie do wykonania tego.

Jak można się spodziewać, jest już siedem odpowiedzi, z których należy skorzystać grep. Ale wydaje mi się, że do tej pory byłem jedyną osobą, która zauważyła twoje pytanie, którego używasz vim. Jako takie, chociaż można używać grepod wewnątrz vim, można również użyć vim„s wbudowane narzędzie. Jest to wywoływane za pomocą :vimgreppolecenia.

Aby wyszukać „wszystkie pliki źródłowe C w bieżącym katalogu w poszukiwaniu wywołań funkcji toUpperCase()”, należy wpisać vimpolecenie

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

Wynikowa lista dopasowań jest automatycznie ładowana do listy szybkich poprawek, dostępnej za pomocą jednego z nich (zobacz subtelną różnicę w pomocy online)

:copen
:cwin

Aby znaleźć definicję funkcji , a nie wywołania, ctagsjest to narzędzie, jak wspomniano w Gillesodpowiedzi , w połączeniu z poleceniami :tjumplub :tselect.

Dlaczego warto korzystać :vimgrep?

Pomoc on-line ( :help grep) wylicza kilka powodów, których tutaj nie będę papugować. Oprócz tego porównaj działanie :vimgrepz dietbuddhaodpowiedzią . dietbuddhaWiersz poleceń wyświetla osobny grepproces dla każdego pliku źródłowego C. Nie stosuje się nawet xargsdo zmniejszenia tego narzutu. I nadal musisz jakoś przeanalizować dane wyjściowe, aby wywołać edytor tekstowy na odpowiednich plikach źródłowych po zakończeniu. :vimgrepwcale nie rozwidla wielu dodatkowych procesów, a korzystanie z rezultatów to sama prostota. Samo wybranie jednego z wpisów na wynikowej liście poprawek automatycznie ustawia kursor w odpowiednim wierszu odpowiedniego pliku źródłowego.

W rzeczywistości robi dokładnie to, co napisałeś, robiłbyś ręcznie, z wyjątkiem automatycznego. To zautomatyzowany sposób wykonywania tych czynności edytora tekstu. Ładuje plik tak, jakby był ładowany ręcznie, wyszukuje w nim wyrażenie regularne (używając tej samej składni wyrażeń regularnych, z której korzystasz już gdzie indziej vim), rejestruje miejsca, w których występują dopasowania, a następnie zwalnia plik.

JdeBP
źródło
2

Tak, narzędzie to się nazywa grep.

Polecenie grep przeszukuje jeden lub więcej plików wejściowych w poszukiwaniu linii zawierających dopasowanie do określonego wzorca. Domyślnie grep drukuje pasujące linie.

Podstawowe użycie to:

grep something somewhere

Lub dokładniej:

grep [some options] pattern file

W bardzo prostym przypadku rekurencyjnie chcesz przeszukiwać wszystkie pliki, dlatego podajesz -ropcję. Jeśli nie przejmujesz się pisaniem wielkimi lub małymi literami, ustaw -iopcję rozróżniania wielkości liter .

grep -ri "touppercase()" .

Jeśli chcesz tylko pasujące części, skorzystaj z -oopcji.

Grep może używać wyrażeń regularnych i ma ogromny podręcznik .

slhck
źródło
2

grepto standardowa odpowiedź - użycie flagi -r do wyszukiwania rekurencyjnego lub w połączeniu z find(dyskusja i przykłady w innych pytaniach na tej stronie, takich jak ta )

Moim ulubionym wyborem jest ostatnio ack. Prawdopodobnie nie jest zainstalowany na twoim komputerze, ale możesz zainstalować za pomocą apt-get na Ubuntu lub po prostu pobrać. Linki, instrukcje i powody, dla których jest lepszy niż grep, są dostępne na stronie http://betterthangrep.com/

Doug Harris
źródło
1

find i grep

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

dlaczego nie tylko grep?

grep -r string .przejdzie przez wszystkie pliki w bieżącym katalogu. Jeśli masz pliki obiektowe lub inne pliki binarne, możesz odzyskać zgodność z wynikami binarnymi, inaczej. dżonka. Jeśli w podkatalogu masz również pliki FOSO lub pliki urządzeń, możesz mieć nieznane / niezamierzone konsekwencje.

grep string *.cprzeszukuje tylko bieżące .cpliki katalogów .

grep string **/*.c przeszukuje wszystkie podkatalogi. Jeśli jednak masz bardzo dużą liczbę .cplików, istnieje ryzyko przekroczenia maksymalnej liczby rozszerzeń globu powłoki. Ekspansja musi także nastąpić jako pierwsza, co oznacza pełne przejście drzewa, zanim grepzacznie się.

dietbuddha
źródło
0

Grep załatwi sprawę, ale odrobina dodatkowego skryptu pomoże znaleźć nazwę pliku i dokładną linię, do której się odwołuje. Jeśli to jest to, co chcesz, uważam, że następujące działa dobrze. Mam go zapisany jako skrypt powłoki i przekazuję mu wartość, którą chcę jako pierwszą opcję wiersza poleceń.

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
Tim Brigham
źródło
3
grep ma opcję -H, która już to robi. grep -Hn cokolwiek *
Roy Rico
Naucz się czegoś nowego każdego dnia .. Dzięki @Roy Rico
Tim Brigham
0

Interesujące jest dla mnie to, że nikt nie odpowiedział na twoje pytanie: „jak mogę sprawdzić, czy w plikach znajdujących się w bieżącym katalogu istnieje określony ciąg znaków”. O ile mi wiadomo, nie ma opcji grep, która zwraca tylko to, czy znaleziono dopasowanie w grupie plików. Najbliższą opcją jest -l, aby wyświetlić listę nazw plików. Najbliższa odpowiedź spośród tych jak dotąd dotyczy czasu, z pewnymi drobnymi poprawkami:

#!/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"

Możesz uczynić ten skrypt powłoki bardziej ogólnym, akceptując drugi argument rozszerzenia pliku bez większych problemów.

doug

SnoopDougieDoug
źródło