นี่คือวิธีการจับคู่สายอักขระหลายตัวแบบไม่โลภอย่างแน่นหนาโดยใช้ sed ช่วยบอกว่าคุณต้องการที่จะเปลี่ยนทุกfoo...bar
การ<foo...bar>
ดังนั้นสำหรับตัวอย่างเช่นการป้อนข้อมูลนี้:
$ cat file
ABC foo DEF bar GHI foo KLM bar NOP foo QRS bar TUV
ควรเป็นผลลัพธ์นี้:
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV
ในการทำเช่นนั้นคุณจะแปลง foo และ bar เป็นอักขระแต่ละตัวจากนั้นใช้การปฏิเสธของอักขระเหล่านั้นระหว่างพวกเขา:
$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/g; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV
ในด้านบน:
s/@/@A/g; s/{/@B/g; s/}/@C/g
กำลังแปลง{
และ}
สตริงตัวยึดตำแหน่งที่ไม่สามารถมีอยู่ในอินพุตดังนั้นตัวอักษรเหล่านั้นจะพร้อมใช้งานสำหรับการแปลงfoo
และbar
ถึง
s/foo/{/g; s/bar/}/g
กำลังแปลงfoo
และbar
ไปยัง{
และ}
ตามลำดับ
s/{[^{}]*}/<&>/g
กำลังดำเนินการ op ที่เราต้องการ - แปลงfoo...bar
เป็น<foo...bar>
s/}/bar/g; s/{/foo/g
คือการแปลง{
และ}
กลับไปและfoo
bar
s/@C/}/g; s/@B/{/g; s/@A/@/g
กำลังแปลงสตริงตัวยึดตำแหน่งกลับไปเป็นอักขระดั้งเดิม
โปรดทราบว่าข้างต้นไม่พึ่งพาสายอักขระใด ๆ ที่ไม่มีอยู่ในอินพุตเนื่องจากสตริงดังกล่าวผลิตในขั้นตอนแรกและไม่สนใจว่า regexp ใด ๆ ที่คุณต้องการจับคู่เกิดขึ้นเนื่องจากคุณสามารถใช้งานได้{[^{}]*}
บ่อยครั้งเท่าที่จำเป็น ในนิพจน์เพื่อแยกการจับคู่ที่แท้จริงที่คุณต้องการและ / หรือด้วยตัวดำเนินการจับคู่ตัวเลขเช่นเพื่อแทนที่เหตุการณ์ที่สองเท่านั้น:
$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/2; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC foo DEF bar GHI <foo KLM bar> NOP foo QRS bar TUV