ท่อพบใน grep -v


18

ฉันพยายามค้นหาไฟล์ทั้งหมดที่เป็นประเภทที่แน่นอนและไม่มีสตริงที่แน่นอน ฉันพยายามที่จะไปเกี่ยวกับมันโดยท่อค้นหาเพื่อ grep -v

ตัวอย่าง:

find -type f -name '*.java' | xargs grep -v "something something"

ดูเหมือนจะใช้งานไม่ได้ ดูเหมือนว่าจะส่งคืนไฟล์ทั้งหมดที่พบคำสั่ง สิ่งที่ฉันพยายามจะทำคือค้นหาไฟล์. java ทั้งหมดที่ตรงกับชื่อไฟล์ที่แน่นอน (เช่นลงท้ายด้วย 'Pb' ใน SessionPb.java) และไม่มี 'ขยาย SomethingSomething "ข้างใน

ความสงสัยของฉันคือการที่ฉันทำผิด ดังนั้นคำสั่งควรมีลักษณะอย่างไรแทน


คุณอาจเพิ่มสิ่งที่ทำให้คุณคิดว่ามันไม่ทำงาน บางทีการแสดงออก grep ของคุณชัดเจนเกินไปหรือไม่ ต้องการ '-i' สำหรับการตอบโต้กรณีหรือไม่ ดูคำตอบของฉันด้านล่างเกินไป ...
lornix

คำตอบ:


21

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

find . -type f -iname "*.java" -exec grep -L "something somethin" {} \+

1
-Lfiles _without_ matchแล้วมีการเจรจาต่อรองเพราะมันหมายถึง ดังนั้นคุณไม่ต้องการ-vตัวเลือกที่นี่
เร่ง

3
ไม่ได้มีเครื่องหมาย + ที่ส่วนท้าย
lynxlynxlynx

2
@ user946850 ทุกครั้งที่ฉันเขียนfind -exec \+มีคนเขียนฉันว่ามันดีกว่าการใช้ xargs ทำไมไม่มีใครดูผู้ชายก่อนเขียนความคิดเห็น? (:
เร่งด่วน

5
@ user946850 จะไม่เทียบเท่ากับ-exec ... {} \+ xargsโปรดอ่านเอกสาร findutils! (ฉันทำงานหนักมากในเรื่องนี้!)
James Youngman

2
@ user946850 ใช่ ความแตกต่างอย่างหนึ่งคือ (โดยค่าเริ่มต้น) xargsประมวลผลอินพุตและแยกอาร์กิวเมนต์บนพื้นที่สีขาว นอกจากนี้ยังมีคำพูดเป็นพิเศษ (โดยค่าเริ่มต้น) xargsเพื่อ -exec ... {} +ทั้งสิ่งเหล่านี้เป็นจริงสำหรับ เวอร์ชันเก่าที่xargsใช้เพื่อพิจารณาขีดล่างเป็นตัวบ่งชี้ EOF แต่นี่ไม่ใช่กรณีอีกต่อไป
James Youngman

7

คุณเกือบจะได้รับมันจริงๆ ...

find . -type f -iname "*.java" -print0 | xargs -0 grep -v "something something"

จุด '.' บอกว่าจะเริ่มจากที่นี่ (คุณแสดงถึงมัน .. แต่ไม่เคยคิด)

- ชื่อใช้การค้นหาตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ในกรณีที่ (หรือในกรณีที่ไม่มี)
-print0ส่งชื่อไฟล์ไปยัง xargs ที่มีตัวอักษร \ x00 ต่อท้ายซึ่งป้องกันปัญหาเกี่ยวกับชื่อไฟล์ที่มีช่องว่าง

'-0' ใน xargs บอกว่าคาดว่าชื่อไฟล์ที่ลงท้ายด้วย \ x00 แทนที่จะส่งกลับ

และคำสั่ง grep ของคุณ ...

ค่อนข้างเข้าใจแล้ว


แก้ไข ::

จากการอัปเดตของคุณ:

find . -type f -iname "*pb.java" -print0 | xargs -0 grep -iL "something"

ควรช่วย (เพิ่ม -L จากคำตอบของ @ รัชงานที่ดี)

ฉันได้รับแนวคิดว่า grep ของคุณต้องการตัวเลือก '-i' หรือชัดเจนน้อยกว่า

ลองคำสั่งในส่วนต่าง ๆ ... ชื่อไฟล์ที่แสดงนี้น่าจะเหมาะสมหรือไม่

find . -type f -iname "*pb.java"

ถ้าเป็นเช่นนั้นแสดงว่าปัญหาของคุณอาจเป็นไปได้ว่ารูปแบบการค้นหา grep ของคุณไม่ตรงกัน

กรณีที่เลวร้ายที่สุดอย่างแน่นอน:

grep -riL "something" *

จะทำงานอีกมากค้นหาทุกสิ่ง แต่ควรให้ผลลัพธ์บางอย่างแก่คุณ


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

หากผู้เขียนคำถามต้องการค้นหาชื่อไฟล์ grep ไม่ควรเป็น 'grep -l -v' ใช่หรือไม่
Bruce Ediger

เขากำลังมองหาเนื้อหาที่เฉพาะเจาะจงในไฟล์ * .java
lornix

xargs -0 grep -v "something something"ควรเป็นxargs -0 grep -v "something something" /dev/nullอย่างอื่นคุณจะได้รับผลลัพธ์แปลก ๆ เมื่อค้นหาไม่มีไฟล์ที่ตรงกัน
James Youngman

{Grin} ใช่ที่ใดที่หนึ่งในนั้นตรรกะมีขนทั้งหมด ไม่มีอะไรที่เหมือนกับการทดสอบแบบลอจิกแบบลอจิกเท็จที่ทำให้คุณปวดหัว
lornix

4

คอมพิวเตอร์กำลังเป็นคอมพิวเตอร์: กำลังทำสิ่งที่คุณบอกให้ทำแทนที่จะทำในสิ่งที่คุณต้องการให้ทำ

grep -v "something something"something somethingพิมพ์ทุกสายที่ไม่ได้มี ตัวอย่างเช่นมันพิมพ์สองบรรทัดในสามบรรทัดต่อไปนี้:

hello world
this is something something
something else

หากต้องการพิมพ์ไฟล์ที่ไม่มีextends SomethingSomethingที่ใด ๆ ให้ใช้-Lตัวเลือก:

grep -L -E 'extends[[:space:]]+SomethingSomething' FILENAME…

grep บางรุ่นไม่มี-Lตัวเลือก (ไม่ได้ระบุโดยPOSIX ) หากคุณไม่มีให้พิมพ์มันออกมาและใช้รหัสส่งคืนเพื่อให้เชลล์การโทรทำสิ่งที่ควรทำแทน

grep -q -E 'extends[[:space:]]+SomethingSomething' FILENAME ||
echo "$FILENAME"

หรือใช้ awk

awk '
    FNR == 1 && NR != 1 && !found { print fn }
    FNR == 1 { fn = FILENAME; found = 0; }
    /extends[[:space:]]+SomethingSomething/ { found = 1 }
    END { if (fn != "" && !found) print fn }
'

บน Linux หรือ Cygwin (หรือระบบอื่นที่มี grep GNU) คุณไม่จำเป็นต้องใช้findเนื่องจากgrepสามารถเรียกซ้ำได้

grep -R --include='*.java' -L -E 'extends[[:space:]]+SomethingSomething'

หากเชลล์ของคุณคือ ksh หรือ bash หรือ zsh คุณสามารถทำให้เชลล์ทำการจับคู่ชื่อไฟล์ได้ ใน bash ให้รันset -o globstarก่อน (คุณสามารถใส่มันไว้ใน~/.bashrc)

grep -L -E 'extends[[:space:]]+SomethingSomething' **/*.java

ว้าวนี่มันดีกว่า ฉันใช้ 'extends (/ s) + SomethingSomething' ซึ่งดูเหมือนจะทำงานได้ไกลที่สุดเท่าที่ฉันจะบอกได้ มีความแตกต่างกับไวยากรณ์นี้กับที่ระบุในรุ่น Extended RegEx หรือไม่
Hyangelo

@Hyangelo \sเป็น GNU grep [[:space:]]ขยายซึ่งผมคิดว่าเป็นสิ่งที่มีความหมายเหมือนกัน
Gilles 'หยุดความชั่วร้าย'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.