Yüzlerce PHP dosyası içeren bir sitede sınıf bildirimi arıyorum. Bunu grep kullanarak geçerli klasörde ve alt klasörlerde nasıl yapabilirim ?
cd
Klasöre girdim ve daha sonra
grep -r 'class MyClass' *.php
Yüzlerce PHP dosyası içeren bir sitede sınıf bildirimi arıyorum. Bunu grep kullanarak geçerli klasörde ve alt klasörlerde nasıl yapabilirim ?
cd
Klasöre girdim ve daha sonra
grep -r 'class MyClass' *.php
Yanıtlar:
Bir grep ile yapmak yerine ctags gibi bir şey kullanmanızı tavsiye ederim . Ancak, isterseniz, böyle bir şey yapabilirsiniz
find <top level dir> -name \*.php | xargs grep "class MyClass"
Bu, elbette, aralarında yalnızca doğru bir boşluk olduğunu varsayar class
ve myClass
bunlar doğru olmayabilir. Gerçi herhangi bir sayıda beyaz boşluk aramak için normal ifadeyi değiştirmek kolaydır.
Kullanıyorsanız -r
, büyük olasılıkla yalnızca geçerli dizini özyinelemeli olarak aramak istersiniz :
grep -r 'class MyClass' .
Yukarıdakilerin sonundaki noktaya dikkat edin.
Söylediğiniz grep
şey, her *.php
dosyayı veya dizini özyinelemeli olarak aramasını istediğinizdi , ancak büyük olasılıkla .php uzantısıyla biten dizinleriniz yoktu. Yukarıda arama yapmak mümkün olan en basit yoludur, ancak her yerde .svn dizinleri olduğunda özellikle sorunlu olan diğer tür dosyaları içerir. Çok fazla başka dosya türünüz yoksa, yukarıdakiler genellikle yeterlidir ve iyi çalışır.
Çoğu grep enkarnasyonunda, aranabilen dosya uzantılarını belirtmenin bir yolu yoktur, bu nedenle genellikle find'ı onunla birlikte kullanırsınız:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;
-iname
grep'in bazı sürümlerinde büyük / küçük harfe duyarlı olmayan bir dosya adı araması yapmak istediğinizi söyler, ancak find'ın GNU olmayan varyantlarının çoğu bunu desteklemez, -name
bunun yerine kullanabilirsiniz .
Yukarıdaki -exec
seçenek, her dosya için grep'i çağırmanın yan etkisine sahiptir, bu da oldukça pahalıdır.
Yine de grep'in diğer sürümleri +
, çalıştırılabilir dosyanın çağrılma sayısını azaltmak için argümanları bir araya getirmeyi söyleyen bir desteği destekler :
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;
Çağrıları azaltmak için sıkça önerilen bir yol, grep'i mümkün olduğunca az kez, ancak gerektiği kadar ateşleyecek xargs kullanmaktır:
find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"
xargs
grep'i komut satırında desteklenen maksimum argüman sayısına kadar aktaracak kadar akıllıdır, ancak yukarıdaki varyasyon boşluklar gibi belirli karakterleri çok iyi işlemez. Örneğin, 'file.php' dosya adı grep'inin argüman olarak 'the' ve argüman olarak 'file.php' alacağı için her ikisi de bulunamazdı. Bunun yerine şunları kullanıyoruz:
find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"
print0
ve -0
birlikte çalışma ve kullanım bağımsız değişkenleri bağımsız değişken tam ve açık bir şekilde tanımlanır, böylece bir boş karakter takip eder.
daha sonra birden fazla alanınız class
veya bir sekmeniz varsa, normal ifadeyi değiştirerek daha fazla karaktere izin vermek isteyebilirsiniz:class[ \t]*MyClass
Bu mesaj StackOverflow'daki diğer örnekler vardır ve .svn dizinleri gibi belirli dizinleri dışlamak için nasıl kullanılacağını gösterir.
grep -r 'class MyClass' *.php
.php ile biten tüm klasörlerde arama yapar
grep -r 'class MyClass' . | grep .php
tüm alt klasörlerde bulunan tüm dosyalarda MyClass sınıfını arayacak, sonra yalnızca .php olanları döndürecektir.
find . -type f -name *.php -print -exec grep \"class MyClass\" {} \;
size bulunduğu satırın içeriğini ve dosyanın yolunu verecektir.
Muhtemelen büyük / küçük harf duyarsızlığı ve boşluk toleransı istersiniz ve grep, geçerli dizinde istenen dosya deseninin herhangi bir örneğini bulamazsa sonlanır. Nereden başlayacağını bilmeli ve olduğu gibi eşleşen hiçbir dosya başlangıç yolu oluşturmaz.
İstenen uzantının en az bir dosyası varsa, egrep -ir komutunu kullanabilirsiniz. find
ve xargs
grep'in başarısız olduğu tek düz (ancak çok büyük) dizinlerle ve ekstra niteleyicilerle (örneğin yalnızca .inc, .php ve php3 dosyalarını aramak istiyorsanız) güçlerini gösterin. Ama benim deneyimimde biraz rahatlık ve hız kaybediyor. İnsan yazılı sınıf beyannameleri için büyük bir sorun boşluk olacaktır. Bu yüzden grep yerine egrep kullanın. Ayrıca ekstra hız için LC_ALL = C. Kolaylık sağlamak için sık sık kullanıyorum:
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
Bu, yine de yorumlarla eşleşebilir // class myclass exists in file
, ancak bunları nispeten küçük buluyorum ve bunlar ile filtrelenebilir... | fgrep -v '//'
Ayrıca, egrep dosya modeline aşağıdaki gibi daha karmaşık dosya maskeleri (örneğin, .inc ve .php dosyalarının çoğunu yakalamak için) dahil edebilirsiniz:
egrep "pattern" *.[ip]*
Bu (ilk seçeneklerle) oldukça hızlı ve çoğunlukla php dosyalarıyla sınırlı olacaktır.
HTH
Biliyorum diyor grep
, ama benim kişisel favorim kullanmaktır ack-grep
:
ack-grep "class MyClass"
Bu özyinelemeli olarak çalışır, bulduğu dosya adını, bulundukları yerdeki satır numaralarını ve vurguları listeler. Özellikle php dosyalarını hedeflemek için çalıştırabilirsiniz:
ack-grep --type-set php:ext:php "path"
Paket çok sayıda seçeneğe sahiptir; Süslü şeyler yapmak için kesinlikle tavsiye ederim (ve ilişkili adam sayfasına göz atarak).
grep -r
vermeyen, istediğiniz şey hakkında bir şeyler söylemek isteyebilirsiniz .