Bash: มีวิธีการค้นหาสตริงเฉพาะในไดเรกทอรีของไฟล์หรือไม่? [ซ้ำ]


47

ซ้ำได้:
ค้นหารูปแบบข้อความใน linux

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

สมมติว่าคุณกำลังมองหาฟังก์ชั่น 'toUpperCase ()' ภายในชุดของไฟล์ C ในไดเรกทอรีปัจจุบันของคุณ มีไฟล์จำนวนมากดังนั้นคุณไม่ต้องการเปิดแต่ละไฟล์ด้วยตนเองโดยใช้ vim และตรวจสอบสตริง 'toUpperCase' เพราะมันใช้เวลานาน ถ้าไม่ใช่บรรทัดคำสั่ง bash มีวิธีอื่นที่จะทำสิ่งนี้ได้อย่างมีประสิทธิภาพหรือไม่?

คำตอบ:


64

ด้วยgrep:

grep -R "toUppercase()" *

หรือถ้าคุณติดตั้งack-grepเพียง:

ack-grep "toUppercase"

หากคุณต้องการ จำกัด การค้นหาในไฟล์ C ด้วยack-grep:

ack-grep -cc "toUppercase()"

ack-grepนอกจากนี้ยังสามารถติดตั้งบน OSX ackแต่ปฏิบัติการที่เรียกว่าเพียงแค่


มากเสียจนมีคำถามที่คล้ายกันอย่างน่าสงสัยแล้ว)
เดวิดเพอร์รี

10

เครื่องมือในการค้นหาข้อความมาตรฐานคือgrep

ในการค้นหาสตริงtoUpperCase(ใน.cไฟล์ทั้งหมดในไดเรกทอรีปัจจุบัน:

grep -F 'toUpperCase(' *.c

หากคุณต้องการค้นหาในไดเรกทอรีย่อยด้วย:

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

หากคุณกำลังมองหาการเรียกใช้ฟังก์ชัน C แล้วctagsอาจเหมาะกว่า คุณเรียกใช้มันหนึ่งครั้งในไฟล์ต้นฉบับทั้งหมดของคุณเพื่อสร้างดัชนีของตัวระบุจากนั้นใช้เครื่องมือแก้ไขของคุณเพื่อนำทางระหว่างการโทร เครื่องมือแก้ไขที่เหมือนกันทั้งหมดสามารถใช้TAGSไฟล์ของ ctags ถ้าคุณใช้ Emacs etagsเรียกใช้โปรแกรมที่คล้ายกัน


ctagsจะเป็นประโยชน์สำหรับการหาฟังก์ชั่นคำจำกัดความไม่ได้ทำงานสาย
JdeBP

6

คุณใช้เสียงเรียกเข้า คุณมีเครื่องมือในการทำสิ่งนี้ในตัว

grepคาดมีเจ็ดคำตอบแล้วพูดกับการใช้งาน แต่ฉันดูเหมือนจะเป็นคนเดียวจนถึงตอนนี้ที่สังเกตจากคำถามที่คุณใช้vimอยู่ ดังนั้นแม้ว่าคุณจะสามารถใช้งานได้grepจากภายในvimแต่คุณยังสามารถใช้vimเครื่องมือในตัว สิ่งนี้ถูกเรียกผ่าน:vimgrepคำสั่ง

ในการค้นหา "ไฟล์ต้นฉบับ C ทั้งหมดในไดเรกทอรีปัจจุบันสำหรับการเรียกใช้ฟังก์ชันtoUpperCase()" ให้vimพิมพ์คำสั่ง

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

รายการผลลัพธ์ของการแข่งขันจะถูกโหลดโดยอัตโนมัติไปยังรายการโปรแกรมแก้ไขด่วนซึ่งสามารถเข้าถึงได้ด้วยวิธีใดวิธีหนึ่ง (ดูวิธีใช้ออนไลน์สำหรับความแตกต่างเล็กน้อย)

:copen
:cwin

หากต้องการค้นหาคำจำกัดความของฟังก์ชันแทนที่จะเรียกใช้ctagsเป็นเครื่องมือดังที่กล่าวไว้ในGillesคำตอบของคำตอบร่วมกับคำสั่ง:tjumpหรือ:tselect

ทำไมต้องใช้:vimgrep?

ความช่วยเหลือออนไลน์ ( :help grep) แจกแจงเหตุผลหลายประการซึ่งฉันจะไม่นกแก้วที่นี่ เพิ่มเติมให้กับผู้ที่เปรียบเทียบการกระทำของ:vimgrepกับที่ของ'คำตอบ dietbuddha dietbuddhaบรรทัดคำสั่งของส้อมgrepกระบวนการแต่ละกระบวนการสำหรับแต่ละไฟล์ต้นฉบับ C มันไม่ได้ใช้xargsเพื่อลดค่าใช้จ่าย และคุณยังต้องแยกวิเคราะห์เอาต์พุตเพื่อเรียกใช้ตัวแก้ไขข้อความในไฟล์ต้นฉบับที่เกี่ยวข้องเมื่อเสร็จสิ้น :vimgrepไม่แยกกระบวนการเพิ่มเติมหลายอย่างเลยและการใช้ผลลัพธ์ก็คือความเรียบง่ายนั้นเอง เพียงแค่เลือกรายการใดรายการหนึ่งในรายการ quickfix ผลลัพธ์วางตำแหน่งเคอร์เซอร์บนบรรทัดที่เกี่ยวข้องของไฟล์ต้นฉบับที่เกี่ยวข้อง

อันที่จริงแล้วมันทำสิ่งที่คุณเขียนด้วยมืออย่างแน่นอนยกเว้นโดยอัตโนมัติ นี่เป็นวิธีอัตโนมัติในการดำเนินการแก้ไขข้อความ มันโหลดไฟล์ราวกับว่าโหลดด้วยมือค้นหานิพจน์ทั่วไป (โดยใช้ไวยากรณ์นิพจน์ทั่วไปแบบเดียวกับที่คุณใช้อยู่ในที่อื่นvim) บันทึกตำแหน่งที่เกิดการแข่งขันแล้วยกเลิกการโหลดไฟล์


2

grepใช่เครื่องมือที่เรียกว่า

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

การใช้งานพื้นฐานคือ:

grep something somewhere

หรือเฉพาะเจาะจงมากขึ้น:

grep [some options] pattern file

ในกรณีที่ง่ายมากคุณต้องการค้นหาไฟล์ซ้ำทั้งหมดซ้ำดังนั้นคุณจึงจัดหา-rตัวเลือก หากคุณไม่สนใจเกี่ยวกับตัวพิมพ์ใหญ่หรือพิมพ์เล็กทำให้มันกรณีตายกับ-iตัวเลือก

grep -ri "touppercase()" .

หากคุณต้องการเฉพาะส่วนที่ตรงกันให้ใช้-oตัวเลือก

grep สามารถใช้การแสดงออกปกติและมีคู่มือการใหญ่


2

grepคือคำตอบมาตรฐาน - ใช้ทั้งแฟล็ก -r เพื่อค้นหาแบบซ้ำ ๆ หรือใช้ร่วมกับfind(การอภิปรายและตัวอย่างในคำถามอื่น ๆ ในเว็บไซต์นี้เช่นนี้ )

ทางเลือกที่ดีของฉันเมื่อเร็ว ๆ ackนี้ ไม่น่าจะติดตั้งบนคอมพิวเตอร์ของคุณ แต่คุณสามารถติดตั้งโดยใช้ apt-get บน Ubuntu หรือเพียงแค่ดาวน์โหลด ลิงค์คำแนะนำและเหตุผลที่ดีกว่า grep มีอยู่ที่http://betterthangrep.com/


1

find และ grep

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

ทำไมไม่เท่านั้นgrep?

grep -r string .จะคืนค่าผ่านไฟล์ทั้งหมดในไดเรกทอรีปัจจุบัน หากคุณมีไฟล์ออบเจ็กต์หรือไบนารีอื่น ๆ คุณอาจเปรียบเทียบผลลัพธ์ไบนารีด้วยกันได้ ขยะ. หากคุณมีไฟล์ fifos หรืออุปกรณ์ในไดเรกทอรีย่อยของคุณคุณอาจไม่ทราบ / ไม่ทราบผลที่ตามมา

grep string *.cค้นหา.cไฟล์ไดเรกทอรีปัจจุบันเท่านั้น

grep string **/*.c ค้นหาทุกไดเรกทอรีย่อย อย่างไรก็ตามหากคุณมี.cไฟล์จำนวนมากคุณจะเสี่ยงต่อการขยายเกินจำนวนสูงสุดสำหรับเชลล์ glob การขยายตัวจะต้องเกิดขึ้นก่อนซึ่งหมายความว่าการสำรวจต้นไม้เต็มก่อนที่จะgrepเริ่มต้น


0

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

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

3
grep มีตัวเลือก -H ซึ่งทำสิ่งนี้อยู่แล้ว grep
Roy Rico

เรียนรู้สิ่งใหม่ทุกวัน .. ขอบคุณ @Roy Rico
Tim Brigham

0

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

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

คุณสามารถทำให้เชลล์สคริปต์นี้เป็นแบบทั่วไปโดยยอมรับอาร์กิวเมนต์ที่สองสำหรับส่วนขยายของไฟล์โดยไม่มีปัญหามากเกินไป

ดั๊ก

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