ฉันจะค้นหาสตริงในไฟล์ PHP โดยใช้ "grep" ได้อย่างไร


11

ฉันกำลังค้นหาการประกาศคลาสบนไซต์ที่มีไฟล์ PHP หลายร้อยไฟล์ ฉันจะทำสิ่งนี้ในโฟลเดอร์ปัจจุบันและโฟลเดอร์ย่อยโดยใช้grep ได้อย่างไร

ฉันทดสอบcdไอเอ็นจีไปยังโฟลเดอร์และจากนั้นสิ่งที่ชอบ

grep -r 'class MyClass' *.php

เมื่อสิ่งนี้ย้ายไปที่ superuser คุณอาจต้องการพูดบางอย่างเกี่ยวกับสิ่งที่คุณต้องการที่grep -rไม่ได้ให้

ฉันสับสน - คุณไม่เพียงแค่ตอบตัวเอง? ผลลัพธ์ของบรรทัดนั้นคืออะไร คุณกำลังพยายามเพิ่มประสิทธิภาพต่อไปหรือไม่ โปรดจินตนาการการอ่านคำถามนี้ในฐานะคนอื่นเพราะสับสนและไม่ชัดเจน
meder omuraliev

ความคิดเห็น @other: grep -R คำพูดของเขาจะไม่ให้สิ่งที่เขาต้องการเว้นแต่จบโฟลเดอร์ทั้งหมดที่มี .php ซึ่งอาจเป็นกรณีที่ไม่ ...
เดวิด Oneill

ฉันไม่ได้รับอะไรเลย ฉันคิดว่ามันใช้งานไม่ได้เพราะฉันรู้ว่าพบเมื่อฉันอยู่ในโฟลเดอร์ที่มีไฟล์ในคลาสนี้

ฉันพบไฟล์โดยโชค เมื่อค้นหาไฟล์ในโฟลเดอร์ที่มีไฟล์ PHP ที่มีบรรทัดนั้นจะพบไฟล์นั้น (ไม่จำเป็นต้องใช้ -r) ถ้าฉัน CD ไปที่รูทและทำการค้นหาด้วยการเรียกซ้ำ - มันจะไม่ส่งคืนสิ่งใด

คำตอบ:


24

คุณสามารถลอง

grep -r --include=*.php "search string" /path/to/dir

1
ใช้งานได้ดี ฉันลืมไปเรื่อย ๆ แต่โชคดีที่มีคำตอบนี้อยู่เสมอเพื่อช่วยฉัน :)
GolezTrol

@GolezTrol ดีใจที่รู้ว่า :-)
rahul286

9

ฉันขอแนะนำให้คุณใช้งานctagsแทนการใช้ grep อย่างไรก็ตามถ้าคุณต้องการคุณสามารถทำสิ่งที่ชอบ

 find <top level dir> -name \*.php | xargs grep "class MyClass"

แน่นอนว่าคุณมีช่องว่างระหว่างclassและmyClassที่อาจไม่เป็นจริง มันง่ายที่จะเปลี่ยน regexp เพื่อค้นหาช่องว่างจำนวนเท่าใดก็ได้


4

หากคุณใช้-rคุณอาจต้องการค้นหาซ้ำในไดเรกทอรีปัจจุบันซ้ำ:

grep -r 'class MyClass' .

หมายเหตุช่วงเวลาในตอนท้ายของข้างต้น

สิ่งที่คุณบอกgrepคือคุณต้องการให้มันทำการค้นหา*.phpไฟล์หรือไดเรกทอรีซ้ำทุกครั้งแต่คุณอาจไม่มีไดเรกทอรีที่ลงท้ายด้วยนามสกุล. php ด้านบนเป็นวิธีที่ง่ายที่สุดในการค้นหา แต่ยังรวมถึงไฟล์ประเภทอื่น ๆ ซึ่งเป็นปัญหาโดยเฉพาะอย่างยิ่งเมื่อคุณมีไดเรกทอรี. svn อยู่ทุกที่ หากคุณไม่มีไฟล์ประเภทอื่น ๆ จำนวนมากดังกล่าวข้างต้นโดยทั่วไปเพียงพอและทำงานได้ดี

ส่วนใหญ่ของ grep ไม่มีวิธีระบุนามสกุลไฟล์ที่สามารถค้นหาได้ดังนั้นโดยทั่วไปแล้วคุณใช้ find ร่วมกับมัน:

find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;

-inameบอก grep บางเวอร์ชันว่าคุณต้องการทำการค้นหาชื่อไฟล์โดยไม่ต้องคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ แต่ไม่ใช่ใน GNU รุ่นต่างๆที่ไม่รองรับการค้นหาดังนั้นคุณสามารถใช้-nameแทนได้

-execตัวเลือกดังกล่าวข้างต้นมีผลข้างเคียงของการเรียก grep สำหรับทุกไฟล์ซึ่งเป็นค่าใช้จ่ายที่เป็นธรรม

ยังรุ่นอื่น ๆ ของ grep สนับสนุน+ที่บอกให้พบการผนวกข้อโต้แย้งเข้าด้วยกันเพื่อลดจำนวนการเรียกใช้ของการปฏิบัติการ:

find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;

วิธีที่แนะนำให้ใช้บ่อยเพื่อลดการเรียกใช้คือการใช้ xargs ซึ่งจะทำการไล่ grep ออกให้น้อยที่สุดเท่าที่จะทำได้ แต่ให้มากที่สุดเท่าที่จำเป็น:

find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"

xargsฉลาดพอที่จะส่ง grep จนถึงจำนวนอาร์กิวเมนต์สูงสุดที่สนับสนุนในบรรทัดคำสั่ง แต่รูปแบบข้างต้นไม่รองรับอักขระบางตัวเช่นช่องว่างได้ดี ตัวอย่างเช่นมี 'the file.php' ชื่อไฟล์ grep จะได้รับ 'the' เป็นอาร์กิวเมนต์และ 'file.php' เป็นอาร์กิวเมนต์ดังนั้นทั้งคู่จะไม่พบ เราใช้แทน:

find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"

print0และ-0ทำงานร่วมกันและใช้อาร์กิวเมนต์ตามด้วยอักขระ null เพื่อให้อาร์กิวเมนต์มีการระบุอย่างสมบูรณ์และชัดเจน

ถ้าคุณมีช่องว่างมากกว่าหนึ่งหลังclassหรือแท็บคุณอาจต้องการอนุญาตให้ใช้อักขระเพิ่มเติมโดยเปลี่ยน regex:class[ \t]*MyClass

โพสต์บน StackOverflow มีตัวอย่างอื่นและแสดงวิธีแยกไดเรกทอรีบางรายการเช่นไดเรกทอรี. svn


ค้นหาไฟล์ทั้งหมด ไฟล์ที่ไม่ใช่ไฟล์. php ด้วย
GolezTrol

ฉันได้อัปเดตโพสต์เพื่อรวมตัวอย่างอื่น ๆ อีกมากมาย
Kaleb Pederson


1
grep -r 'class MyClass' *.php

จะค้นหาโฟลเดอร์ทั้งหมดที่มีชื่อลงท้ายด้วย. php

grep -r 'class MyClass' . | grep .php

จะค้นหาคลาส MyClass ในไฟล์ทั้งหมดในโฟลเดอร์ย่อยทั้งหมดจากนั้นส่งคืนเฉพาะไฟล์ที่มี. php อยู่เท่านั้น


1

find . -type f -name *.php -print -exec grep \"class MyClass\" {} \; จะให้เนื้อหาของบรรทัดที่พบในและเส้นทางไปยังไฟล์


1

ในกรณีที่ไฟล์ที่จับคู่อาจมีชื่อโดยพลการคุณควรพิจารณาใช้ -print0

หา -type f -name '* .php' -print0 | xargs -0 grep 'class MyClass'


1
grep -rl 'class MyClass' . --include \*.php

l แสดงชื่อไฟล์เท่านั้น

r คือ recurive

. ค้นหาในโฟลเดอร์ปัจจุบัน

- รวมส่วนขยายของชื่อไฟล์ที่ จำกัด


1

อาจเป็นเพราะคุณต้องการตัวพิมพ์เล็กและตัวพิมพ์เล็กและช่องว่างที่ยอมรับได้และ grep จะยุติหากไม่พบอินสแตนซ์ของรูปแบบไฟล์ที่ต้องการในไดเรกทอรีปัจจุบัน จำเป็นต้องทราบว่าจะเริ่มต้นอย่างไรและไม่มีไฟล์ใดที่ตรงกับการผลิตจึงไม่มีเส้นทางเริ่มต้น

หากมีนามสกุลไฟล์ที่ต้องการอย่างน้อยหนึ่งไฟล์คุณสามารถใช้ egrep -ir findและxargsแสดงพลังของพวกเขาด้วยไดเรกทอรีเดียว (แต่ใหญ่มาก) ที่ grep ล้มเหลวและมีคุณสมบัติเพิ่มเติม (ตัวอย่างเช่นหากคุณต้องการค้นหาไฟล์. inc, .php และ php3 เท่านั้น) แต่มันเสียความสะดวกและความเร็วไปเล็กน้อยในประสบการณ์ของฉัน สำหรับการประกาศในชั้นเรียนของมนุษย์เป็นปัญหาใหญ่ที่จะเป็นช่องว่าง ดังนั้นใช้ egrep แทน grep นอกจากนี้ LC_ALL = C สำหรับความเร็วพิเศษ เพื่อความสะดวกฉันมักจะใช้:

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

สิ่งนี้ยังคงสามารถจับคู่ความคิดเห็นเช่น// class myclass exists in fileแต่ฉันพบว่ามีขนาดค่อนข้างเล็กและสามารถกรองออกด้วย... | fgrep -v '//'

คุณสามารถรวมรูปแบบไฟล์ที่ซับซ้อนมากขึ้น (เช่นเพื่อจับไฟล์. inc และ. php ส่วนใหญ่) ในรูปแบบไฟล์ egrep ดังนี้:

egrep "pattern" *.[ip]*

(พร้อมตัวเลือกแรก) นั้นจะค่อนข้างเร็วและ จำกัด อยู่ที่ไฟล์ php เป็นส่วนใหญ่

HTH


0

ฉันรู้ว่ามันบอกว่าใช้grepแต่สิ่งที่ฉันชอบคือack-grep:

ack-grep "class MyClass"

การดำเนินการนี้จะวนซ้ำแสดงชื่อไฟล์ที่พบผลลัพธ์พร้อมหมายเลขบรรทัดตามที่พบและไฮไลต์ ในการกำหนดเป้าหมายไฟล์ php โดยเฉพาะคุณสามารถเรียกใช้:

ack-grep --type-set php:ext:php "path"

แพ็คเกจนี้มีตัวเลือกให้เลือกมากมาย; ฉันขอแนะนำอย่างแน่นอน (และเรียกดูหน้าเว็บที่เกี่ยวข้อง) เพื่อทำสิ่งที่แฟนซี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.