การจับคู่เชิงลบโดยใช้ grep (เส้นจับคู่ที่ไม่มี foo)


990

ฉันพยายามหาไวยากรณ์สำหรับคำสั่งนี้:

grep ! error_log | find /home/foo/public_html/ -mmin -60

หรือ:

grep '[^error_log]' | find /home/baumerf/public_html/ -mmin -60

error_logฉันต้องการที่จะเห็นไฟล์ทั้งหมดที่ได้รับการแก้ไขยกเว้นสำหรับผู้ที่ตั้งชื่อ

ฉันเคยอ่านเกี่ยวกับที่นี่แต่พบnotรูปแบบ -regex หนึ่งรูป


13
[^ error_log] จะไม่ทำงานอีกต่อไป [] เป็นคลาส char โดยทั่วไป regexp ไม่ดีในรูปแบบเชิงลบ (ยกเว้นว่าเครื่องยนต์ใช้ lookaheads เชิงลบ)
Jaap

คำตอบ:


1755

grep -v เป็นเพื่อนของคุณ:

grep --help | grep invert  

-v, - สลับการจับคู่เลือกบรรทัดที่ไม่ตรงกัน

นอกจากนี้ตรวจสอบที่เกี่ยวข้อง-L(ส่วนประกอบของ-l)

-L, - ไฟล์ที่ไม่มีการจับคู่พิมพ์เฉพาะชื่อไฟล์ที่ไม่มีการจับคู่


124
น่ากล่าวถึงว่าสำหรับ-eตัวเลือกการจับคู่ (เชิงลบ) หลายรายการสามารถใช้:grep -v -e 'negphrase1' -e 'negphrase2'
Babken Vardanyan

31
คล้ายกับความคิดเห็นจาก @ Babken-Vardanyan ยัง - สามารถใช้ท่อเพื่อเข้าร่วมการแข่งขันหลายรายการเช่นgrep -v 'negphrase1|negphrase2|negphrase3'
Nicholas Adams

13
ความคิดเห็นล่าสุดไม่เหมือนกับที่จะค้นหาสิ่งที่ไม่ตรงกันทั้งคู่แทนที่จะเป็นอย่างใดอย่างหนึ่ง นั่นคือถ้ามันตรงกับที่หนึ่ง แต่ไม่อื่น ๆ ที่ยังคงพิมพ์ ลองทั้งสองวิธีด้วยสายอักขระที่ไม่คล้ายกัน
Evan Langlois

7
@EvanLanglois - บังคับให้ grep ตีความรูปแบบเป็นนิพจน์ปกติที่ขยายโดยใช้-Eงานเช่น grep -vE 'negphrase1|negphrase2|negphrase3'
Zlemini

1
@ OlleHärstedtผมคิดว่าผมเข้าใจผิดสถานการณ์ของคุณในความคิดเห็นก่อนหน้าของฉันต่อไปนี้อาจจะเป็นสิ่งที่คุณกำลังมองหาgrep "" /dev/null * | grep foo | grep -v bar | cut -d: -f1 | sort -u( ทำไม grep ครั้งแรก?มีวิธีเสมอ :))
Motti

139

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

บรรทัดที่ไม่มีfoo:

awk '!/foo/'

บรรทัดที่ไม่มีfooหรือbar:

awk '!/foo/ && !/bar/'

บรรทัดที่ไม่มีfooหรือbarประกอบด้วยอย่างใดอย่างหนึ่งfoo2หรือbar2:

awk '!/foo/ && !/bar/ && (/foo2/ || /bar2/)'

และอื่น ๆ


2
ที่จริงแล้วค่อนข้างเย็น คุณไม่จำเป็นต้องเรียนรู้ภาษา awk ทั้งหมดเพื่อจัดกลุ่ม regexp กับตัวดำเนินการเชิงตรรกะ ขอบคุณสำหรับคำตอบนี้!
ปีเตอร์ต.

1
ว่าสิ่งที่ฉันกำลังมองหาขอบคุณมาก
mmrs151

13

ในกรณีของคุณคุณคงไม่ต้องการใช้ grep แต่เพิ่มประโยคคำสั่งลบแทนคำสั่ง find แทน

find /home/baumerf/public_html/ -mmin -60 -not -name error_log

หากคุณต้องการรวมไวลด์การ์ดไว้ในชื่อคุณจะต้องหลีกเลี่ยงพวกมันเช่นเพื่อแยกไฟล์ด้วยคำต่อท้าย. log:

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