Saya mencari deklarasi kelas di situs dengan ratusan file PHP. Bagaimana saya bisa melakukan ini di folder saat ini dan subfolder menggunakan grep ?
Saya menguji cd
ke folder dan kemudian sesuatu seperti
grep -r 'class MyClass' *.php
Saya mencari deklarasi kelas di situs dengan ratusan file PHP. Bagaimana saya bisa melakukan ini di folder saat ini dan subfolder menggunakan grep ?
Saya menguji cd
ke folder dan kemudian sesuatu seperti
grep -r 'class MyClass' *.php
Jawaban:
Saya sarankan Anda menggunakan sesuatu seperti ctag daripada melakukannya dengan grep. Namun, jika Anda mau, Anda bisa melakukan sesuatu seperti
find <top level dir> -name \*.php | xargs grep "class MyClass"
Ini tentu saja mengasumsikan bahwa Anda hanya memiliki satu ruang di antara class
dan myClass
yang mungkin tidak benar. Sangat mudah untuk mengubah regexp untuk mencari sejumlah spasi putih.
Jika Anda menggunakan -r
, Anda mungkin ingin secara rekursif mencari hanya direktori saat ini :
grep -r 'class MyClass' .
Perhatikan periode pada akhir di atas.
Apa yang Anda katakan grep
adalah bahwa Anda ingin mencari secara rekursif setiap *.php
file atau direktori , tetapi Anda kemungkinan tidak memiliki direktori yang berakhir dengan ekstensi .php. Di atas adalah cara termudah untuk melakukan pencarian tetapi juga termasuk file dari jenis lain yang sangat bermasalah ketika Anda memiliki direktori .svn di mana-mana. Jika Anda tidak memiliki banyak jenis file lain, yang di atas umumnya cukup dan berfungsi dengan baik.
Sebagian besar inkarnasi grep tidak memiliki cara untuk menentukan ekstensi file yang dapat dicari, jadi Anda biasanya menggunakan find bersama dengan itu:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;
-iname
memberi tahu beberapa versi grep bahwa Anda ingin melakukan pencarian nama file case-insensitive, tetapi banyak varian non GNU find tidak mendukungnya, jadi Anda bisa menggunakannya -name
.
The -exec
opsi di atas memiliki efek samping menyerukan grep untuk setiap file, yang cukup mahal.
Masih ada versi lain dari dukungan grep +
yang memberitahu find untuk menambahkan argumen bersama-sama untuk mengurangi jumlah doa yang dapat dieksekusi:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;
Cara yang sering disarankan untuk mengurangi doa adalah menggunakan xargs yang akan mengaktifkan grep sesering mungkin tetapi sesering yang diperlukan:
find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"
xargs
cukup cerdas untuk meneruskan grep hingga jumlah maksimum argumen yang didukung pada baris perintah, tetapi variasi di atas tidak menangani karakter tertentu seperti spasi dengan sangat baik. Sebagai contoh, adalah 'file.php' nama file grep akan menerima 'the' sebagai argumen dan 'file.php' sebagai argumen sehingga keduanya tidak akan ditemukan. Sebaliknya, kami menggunakan:
find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"
print0
dan -0
bekerja bersama dan menggunakan argumen yang diikuti oleh karakter nol sehingga argumen tersebut sepenuhnya dan tidak ambigu diidentifikasi.
Jika Anda memiliki lebih dari satu spasi setelahnya class
, atau tab, Anda mungkin ingin mengizinkan lebih banyak karakter dengan mengubah regex:class[ \t]*MyClass
Posting di StackOverflow ini memiliki contoh lain dan menunjukkan cara mengecualikan direktori tertentu, seperti direktori .svn.
grep -r 'class MyClass' *.php
akan mencari melalui semua folder dengan nama yang diakhiri dengan .php
grep -r 'class MyClass' . | grep .php
akan mencari kelas MyClass di semua file di semua sub folder, kemudian hanya mengembalikan yang memiliki .php di dalamnya.
find . -type f -name *.php -print -exec grep \"class MyClass\" {} \;
akan memberi Anda konten dari garis yang ditemukannya serta jalur ke file.
Mungkin Anda menginginkan ketidakpekaan huruf dan toleransi spasi, dan grep akan berhenti jika tidak menemukan contoh pola file yang diinginkan dalam direktori saat ini. Perlu tahu di mana untuk memulai, seolah-olah, dan tidak ada file yang cocok tidak menghasilkan jalur awal.
Jika setidaknya ada satu file dari ekstensi yang diinginkan, maka Anda dapat menggunakan egrep -ir. find
dan xargs
tunjukkan kekuatan mereka dengan direktori flat (tapi sangat besar) tunggal yang gagal gagal dan kualifikasi tambahan (misalnya jika Anda ingin mencari file .inc, .php, dan php3 saja). Tapi itu kehilangan sedikit kenyamanan dan kecepatan dalam pengalaman saya. Untuk deklarasi kelas tertulis manusia masalah besar akan menjadi spasi. Jadi gunakan egrep bukan grep. LC_ALL = C juga untuk kecepatan ekstra. Untuk kenyamanan, saya sering menggunakan:
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
Ini masih dapat mencocokkan komentar, seperti // class myclass exists in file
, tetapi saya menemukan itu relatif kecil, dan mereka dapat disaring... | fgrep -v '//'
Anda juga dapat menyertakan topeng file yang lebih kompleks (misalnya, untuk menangkap sebagian besar file .inc dan .php) pada pola file egrep seperti:
egrep "pattern" *.[ip]*
Itu (dengan opsi pertama) akan sangat cepat dan sebagian besar terbatas pada file php.
HTH
Aku tahu itu mengatakan menggunakan grep
, tapi favorit pribadi saya adalah untuk digunakan ack-grep
:
ack-grep "class MyClass"
Ini berjalan secara rekursif, daftar nama file yang ditemukan hasilnya, dengan nomor baris untuk tempat mereka ditemukan, dan highlight. Untuk secara khusus menargetkan file php Anda dapat menjalankan:
ack-grep --type-set php:ext:php "path"
Paket ini memiliki banyak pilihan; Saya pasti akan merekomendasikannya (dan menelusuri halaman man terkait) untuk melakukan hal-hal mewah.
grep -r
tidak memberi Anda.