GNU Grep สามารถส่งออกกลุ่มที่เลือกได้หรือไม่?


47

เป็นไปได้ไหมที่จะใช้ GNU grep เพื่อรับกลุ่มที่ตรงกันจากนิพจน์

ตัวอย่าง:

echo "foo 'bar'" | grep -oE "'([^']+)'"

อันไหนจะเอาท์พุท "'บาร์'" แต่ฉันต้องการเพียงแค่ "บาร์" โดยไม่ต้องส่งผ่าน grep อีกครั้ง (เช่น. รับกลุ่มที่ตรงกัน) เป็นไปได้ไหม

คำตอบ:


50

คุณสามารถใช้sedสำหรับสิ่งนี้ ใน BSD sed:

echo "foo 'bar'" | sed -E "s/.*'([^']+)'.*/\\1/"

หรือไม่มี-Eตัวเลือก:

sed "s/.*'\([^']\+\)'.*/\1/"

วิธีนี้ใช้ไม่ได้กับอินพุตหลายบรรทัด เพื่อที่คุณต้องการ:

sed -n "s/.*'\([^']\+\)'.*/\1/p"

ขอบคุณที่ลืมเรื่องเสด แต่การที่จะชี้แจง sed ไม่ได้ใช้ -E อาร์กิวเมนต์ ..
Torandi

หืมมันทำบนเครื่องของฉัน (Mac OS X) ในการตรวจสอบเพิ่มเติมในหน้า man: "ตัวเลือก -E, -a และ -i เป็นส่วนเสริม FreeBSD ที่ไม่ได้มาตรฐานและอาจไม่มีในระบบปฏิบัติการอื่น"
jtbandes

1
ดูเหมือนว่าสำหรับฉัน
Torandi

1
@ jtbandes: คุณไม่จำเป็นต้องใช้คุณสมบัติเพิ่มเติมสำหรับการแสดงออกนี้ .. ฉันเพียงแค่ต้องมี 3 ตัวอักษรสำหรับการ( ) +ใช้งาน\( \) \+: นี่เป็นสิ่งเดียวกัน:sed "s/.*'\([^']\+\)'.*/\1/"
Peter.O

2
วิธีนี้ใช้ไม่ได้กับอินพุตหลายบรรทัด สำหรับสิ่งที่คุณต้องการ: sed -n "s/.*'\([^']\+\)'.*/\1/p"
phreakhead

28

ในขณะที่ grep ไม่สามารถส่งออกกลุ่มเฉพาะได้คุณสามารถใช้ lookahead และอยู่เบื้องหลังการยืนยันเพื่อให้ได้สิ่งที่คุณต้องการ:

echo "foo 'bar'" | grep -Po "(?<=')[^']+(?=')"


8
grep -Pไม่สามารถใช้ได้กับทุกแพลตฟอร์ม แต่ถ้าเป็นเช่นนั้นการใช้ lookahead / behind เป็นวิธีที่ดีมากในการแก้ปัญหา
Sébastien

1
grep ฉลาดด้วยการยืนยันที่อยู่เบื้องหลัง? มันทำงานอย่างไรกับการมองด้านหลังที่ยาวนาน? มันเป็นการรวมเอา look-behinds เข้ากับ"ต้นไม้คำต่อท้าย"กับ regex ที่เหลือบ้างไหม?
Ross Rogers

3

คุณสามารถใช้\Kเพื่อรีเซ็ตและทิ้งข้อความการจับคู่ทางซ้ายพร้อมกับ lookahead ซึ่งไม่ได้เพิ่มไว้ในข้อความการจับคู่:

$ echo "foo 'bar'" | grep -oP "'\K[^']+(?=')"
bar

greu GNU เท่านั้น

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