ใช้การสลับ“ |” ใน regex ของ sed


78

ฉันใช้ sed รุ่น GNU sed เวอร์ชั่น 4.2.1 ฉันต้องการใช้ตัวเลือก "|" สัญลักษณ์ในนิพจน์ย่อย ตัวอย่างเช่น :

echo "blia blib bou blf" | sed 's/bl\(ia|f\)//g'

ควรกลับมา

" blib bou "

แต่มันกลับมา

"blia blib bou blf".

ฉันจะได้ผลลัพธ์ที่คาดหวังได้อย่างไร

คำตอบ:


110

"|" ยังต้องการแบ็กสแลชเพื่อให้ได้ความหมายพิเศษ

echo "blia blib bou blf" | sed 's/bl\(ia\|f\)//g'

จะทำในสิ่งที่คุณต้องการ

อย่างที่คุณทราบหากทุกอย่างล้มเหลวอ่านคู่มือ :-)

คู่มือผู้ใช้ GNU sedส่วนที่3.3 ภาพรวมของไวยากรณ์นิพจน์ปกติ :

`REGEXP1 \ | REGEXP2'

จับคู่อย่างใดอย่างหนึ่ง REGEXP1 หรือ REGEXP2

หมายเหตุแบ็กสแลช ...

น่าเสียดายที่ไวยากรณ์ของ regex ไม่ได้มาตรฐานจริง ๆ ... มีหลายรูปแบบซึ่งแตกต่างจากสิ่งอื่น ๆ ที่ "อักขระพิเศษ" ต้องการ \ และที่ไม่ได้ ในบางตัวมันสามารถกำหนดค่าได้หรือขึ้นอยู่กับสวิทช์ (เช่นเดียวกับใน GNU grepซึ่งคุณสามารถสลับระหว่างภาษาถิ่น regex ที่แตกต่างกันสามแบบ)

คำตอบโดยเฉพาะอย่างยิ่งนี้สำหรับsed GNU มีsedตัวแปรอื่น ๆเช่นชุดที่ใช้ใน BSD ซึ่งทำงานแตกต่างกัน


35
สำหรับคนอื่นที่สับสนโดยคำตอบนี้ \ | ใช้งานได้เฉพาะใน gnu sed (gsed บน os x) ไม่ใช่ vanilla sed (sed บน os x)
Andrew Hancox

@AndrewHancox ขอบคุณมาก! ฉันกำลังจะดึงผมทั้งหมดออกจากหัวของฉัน (และจนถึงตอนนี้ฉันทำได้ค่อนข้างดีเมื่อเทียบกับผู้จัดการของฉันบนหน้าผม) - ฉันรู้ว่าฉันรู้จัก RegEx พอที่จะลอง | และ \ | แต่ฉันไม่เคยคิดเกี่ยวกับความจริงที่ว่า OSX อาจใช้ sed non-gnu จริง ๆ
phatskat

8
เวอร์ชัน BSD / OS X มาตรฐานsedรองรับการสลับ แต่เฉพาะกับไวยากรณ์ "ขยาย" regex ( -E) - ซึ่งหมายความว่าไม่มีแบ็กสแลชบนไพพ์หรือวงเล็บ:echo "blia blib bou blf" | sed -E 's/bl(ia|f)//g'
Mark Reed

2
ฉันแก้ไขคำตอบของฉันเพื่อทราบว่าสำหรับ GNU เท่านั้น
sleske

22

เนื่องจากมีความคิดเห็นหลายประการเกี่ยวกับsedการใช้งานที่ไม่ใช่ Gnu : อย่างน้อยใน OS X คุณสามารถใช้-Eอาร์กิวเมนต์เพื่อ  sed:

ตีความนิพจน์ทั่วไปเป็นนิพจน์ปกติแบบขยาย (ทันสมัย) แทนนิพจน์ทั่วไปพื้นฐาน (BRE's) หน้าคู่มือ re_format (7) อธิบายอย่างสมบูรณ์ทั้งสองรูปแบบ

จากนั้นคุณสามารถใช้อักขระเมตาแสดงออกปกติโดยไม่ต้องหลบหนี ตัวอย่าง:

$ echo "blia blib bou blf" | sed -E 's/bl(ia|f)//g'
 blib bou 

12

GNU sed ยังรองรับ-rตัวเลือก (นิพจน์ปกติแบบขยาย) ซึ่งหมายความว่าคุณไม่ต้องหลบหนีจาก metacharacters:

echo foohello barhello | sed -re "s/(foo|bar)hello/hi/g"

เอาท์พุท:

hi hi

ใช่-rตัวเลือกมีประโยชน์จริง ๆ สำหรับการอ่านนิพจน์ นั่นควรเป็นคำตอบที่ยอมรับได้
рüффп

9

The \|ไม่ทำงานกับ sed บน Solaris 10 เช่นกัน สิ่งที่ฉันทำก็คือใช้

perl -p -e 's/bl(ia|f)//g'

2
+1 สำหรับการพกพาเนื่องจากถ้าระบบมี Perl มันจะใช้ไวยากรณ์นี้เสมอซึ่งต่างจาก sed
evilsoup


1

ใน GnuWin32 บน Windows sed sed "s/thing1\|thing2/ /g" source > destinationไวยากรณ์คือ

เครื่องหมายคำพูดต้องเป็นประเภท"- นี่คือ "จำเป็นต้องมี" เพื่อให้คำสั่งแยกวิเคราะห์

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