Szukam deklaracji klasy na stronie z setkami plików PHP. Jak mogę to zrobić w bieżącym folderze i podfolderach za pomocą grep ?
Przetestowałem cd
ing do folderu, a potem coś podobnego
grep -r 'class MyClass' *.php
Szukam deklaracji klasy na stronie z setkami plików PHP. Jak mogę to zrobić w bieżącym folderze i podfolderach za pomocą grep ?
Przetestowałem cd
ing do folderu, a potem coś podobnego
grep -r 'class MyClass' *.php
Odpowiedzi:
Radziłbym używać czegoś takiego jak ctags zamiast robić to z grep. Jeśli jednak chcesz, możesz zrobić coś takiego
find <top level dir> -name \*.php | xargs grep "class MyClass"
To oczywiście zakłada, że masz tylko jedną przestrzeń pomiędzy class
i myClass
który nie może być prawda. Łatwo jest jednak zmienić wyrażenie regularne, aby wyszukać dowolną liczbę białych znaków.
Jeśli używasz -r
, prawdopodobnie chcesz rekurencyjnie przeszukać tylko bieżący katalog :
grep -r 'class MyClass' .
Zwróć uwagę na kropkę na końcu powyższego.
Powiedziałeś, grep
że chcesz rekurencyjnie przeszukiwać każdy *.php
plik lub katalog , ale prawdopodobnie nie masz żadnych katalogów, które zakończyłyby się rozszerzeniem .php. Powyższe jest najprostszym możliwym sposobem wyszukiwania, ale obejmuje również pliki innych typów, co jest szczególnie problematyczne, gdy wszędzie masz katalogi .svn. Jeśli nie masz wielu innych typów plików, powyższe jest ogólnie wystarczające i działa dobrze.
Większość inkarnacji grep nie ma sposobu na określenie rozszerzeń plików, które można przeszukiwać, dlatego zwykle używasz find w połączeniu z nim:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;
-iname
mówi niektórym wersjom grep, że chcesz wyszukiwać nazwy plików bez rozróżniania wielkości liter, ale wiele wariantów wyszukiwania innych niż GNU nie obsługuje tego, więc możesz użyć -name
zamiast tego.
Powyższa -exec
opcja ma efekt uboczny wywołania grep dla każdego pliku, co jest dość kosztowne.
Jeszcze inne wersje grep obsługują a, +
który każe znaleźć, aby dołączyć argumenty razem, aby zmniejszyć liczbę wywołań pliku wykonywalnego:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;
Często zalecanym sposobem ograniczenia wywołań jest użycie xargs, które wystrzelą grep tak mało razy, jak to możliwe, ale tyle razy, ile to konieczne:
find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"
xargs
jest wystarczająco inteligentny, aby przekazać grep do maksymalnej liczby argumentów obsługiwanych w wierszu poleceń, ale powyższa odmiana nie obsługuje zbyt dobrze niektórych znaków, takich jak spacje. Na przykład, jeśli „plik.php” nazwa pliku grep otrzyma „argument” jako argument i „plik.php” jako argument, więc oba nie zostaną znalezione. Zamiast tego używamy:
find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"
print0
oraz -0
współpracuj i używaj argumentów, po których następuje znak null, aby argument był całkowicie i jednoznacznie zidentyfikowany.
Jeśli kiedykolwiek masz więcej niż jedną spację class
lub tabulator, możesz zezwolić na więcej znaków, zmieniając wyrażenie regularne:class[ \t]*MyClass
Ten post na StackOverflow zawiera inne przykłady i pokazuje, jak wykluczyć niektóre katalogi, takie jak katalogi .svn.
Korzystanie z kiedykolwiek wspaniały ACK ,
ack --php 'class MyClass'
grep -r 'class MyClass' *.php
przeszuka wszystkie foldery o nazwach kończących się na .php
grep -r 'class MyClass' . | grep .php
wyszuka klasę MyClass we wszystkich plikach we wszystkich podfolderach, a następnie zwróci tylko te, które zawierają .php.
find . -type f -name *.php -print -exec grep \"class MyClass\" {} \;
poda zawartość linii, w której się znajduje, oraz ścieżkę do pliku.
Prawdopodobnie chcesz rozróżniać małe i wielkie litery oraz tolerancję spacji, a grep zakończy działanie, jeśli nie znajdzie żadnych instancji żądanego wzorca pliku w bieżącym katalogu. Musi wiedzieć, od czego zacząć, a żadne dopasowane pliki nie powodują utworzenia ścieżki początkowej.
Jeśli istnieje co najmniej jeden plik o pożądanym rozszerzeniu, możesz użyć egrep -ir. find
i xargs
pokazują swoją moc za pomocą pojedynczych płaskich (ale bardzo dużych) katalogów, w których grep się nie włącza, oraz dodatkowych kwalifikatorów (na przykład, jeśli chcesz wyszukiwać tylko pliki .inc, .php i php3). Ale w moim doświadczeniu traci sporo wygody i szybkości. Dla ludzkich pisemnych deklaracji klasowych dużym problemem będzie spacja. Więc użyj egrep zamiast grep. Również LC_ALL = C dla dodatkowej prędkości. Dla wygody często używam:
LC_ALL=C egrep -irn "class[ ]*myclass([ ]|\n)" * | egrep "\.(inc|php[35]?)"
-i -- case insensitive
-r -- recursive for all file pattern (here *)
-n -- include the line number
LC_ALL=C -- search in ASCII, not in utf8, this is much faster.
[ ]* -- match any number of spaces before the class name
([ ]|\n) -- match a space or newline after the classname
To może nadal pasować do komentarzy, takich jak // class myclass exists in file
, ale uważam, że są one stosunkowo małe i można je odfiltrować... | fgrep -v '//'
Możesz również dołączyć bardziej złożone maski plików (na przykład, aby złapać większość plików .inc i .php) we wzorcu pliku egrep, tak jak:
egrep "pattern" *.[ip]*
To (z pierwszymi opcjami) będzie dość szybkie i głównie ograniczone do plików php.
HTH
Wiem, że to mówi używanie grep
, ale moim osobistym ulubionym jest używanie ack-grep
:
ack-grep "class MyClass"
Działa rekurencyjnie, wyświetla nazwę pliku, w którym znajduje wyniki, wraz z numerami wierszy, w których zostały znalezione, i wyróżnia. Aby specjalnie celować w pliki php, możesz uruchomić:
ack-grep --type-set php:ext:php "path"
Pakiet ma wiele opcji; Zdecydowanie poleciłbym to (i przeglądanie powiązanej strony man) do robienia fantazyjnych rzeczy.
grep -r
nie dało.