ลองใช้สคริปต์ sed นี้:
มันแฮ็คมากและอาศัยสองสิ่ง: ข้อความไม่มีสัญลักษณ์ '|' และบรรทัดสุดท้ายเท่านั้นที่เริ่มต้นด้วย 'http:'
:again
${
s/\n/|/g
# to include first part too
s/^/|/
:next
# modify last non processed part
s/\(.*\)|\([^|]\+\)|\(.*\)\(http:.*\)/\1|\4\/\2\n\3\4/
t next
# remove unneeded guard
s/^|//
# remove prefix
s/\(.*\n\)\([^\n]\+\)/\1/
b end
}
N
b again
:end
มันทำงานยังไง?
สมมติว่าเรามีข้อมูลนี้:
aaa
bbb
http://zzz
ก่อนอื่นสคริปต์จะรวมบรรทัดทั้งหมดจากไฟล์ไปยังบัฟเฟอร์ภายใน:
:again
${
# Here internal buffer will be processed
b end
}
N
b again
:end
เป็นรูปแบบที่พบบ่อยมากในสคริปต์ของฉันเมื่อ sed ไม่สามารถประมวลผลข้อความทีละบรรทัด
และอินพุตไม่ใหญ่มาก เริ่มต้นจากสคริปต์บรรทัดแรกจะไม่ขัดจังหวะและ
เพียงอ่านบรรทัดถัดไป ('N') ลงในบัฟเฟอร์จนถึงจุดสิ้นสุด
เมื่อได้รับบรรทัดสุดท้าย ('$') ก็สามารถดำเนินการต่อไปได้ และเมื่อเสร็จแล้ว
หยุด ('b end') เราไม่สามารถใช้ป้ายกำกับที่ไม่สิ้นสุดเพื่อสิ้นสุดได้เพียงแค่ 'b'
ทำงานด้วย แต่ฉันชอบความชัดเจน
ดังนั้นตอนนี้ในบัฟเฟอร์ภายในข้อความนี้:
aaa\nbbb\nhttp://zzz
ถัดไปจะแยกบรรทัดด้วยสัญลักษณ์ '|' แทน '\ n':
s/\n/|/g
# to include first part too
s/^/|/
|aaa|bbb|http://zzz
จากนั้นจะพยายามค้นหารูปแบบนี้
...|text|.....http://...
และเปลี่ยนเป็นสิ่งนี้
...|http://...text\n.....http://...
เนื่องจากธรรมชาติของการใช้ regex ที่มีความโลภการทดแทนจึงเกิดขึ้นตั้งแต่ต้นจนจบ
จุดเริ่มต้นของสตริงในแต่ละขั้นตอนกำจัดหนึ่งสัญลักษณ์ '|':
Initial state of buffer:
|aaa|bbb|http://zzz
After first step:
|aaa|http://zzz/bbb\nhttp://zzz
After second step:
|http://zzz/aaa\nhttp://zzz/bbb\nhttp://zzz
วนถูกจัดระเบียบด้วยความช่วยเหลือของคำสั่ง 'ต่อไป' มันข้ามไปที่ป้ายกำกับ 'ถัดไป'
ถ้าการเปลี่ยนตัวครั้งสุดท้ายสำเร็จ
ถัดไปจะลบยามที่ไม่จำเป็นออก '|' ที่จุดเริ่มต้นของบรรทัด:
s/^|//
http://zzz/aaa\nhttp://zzz/bbb\nhttp://zzz
และบรรทัดสุดท้าย:
s/\(.*\n\)\([^\n]\+\)/\1/
http://zzz/aaa\nhttp://zzz/bbb
ดังนั้นเมื่อมันพิมพ์บัฟเฟอร์ในที่สุดคุณจะได้รับสิ่งนี้:
http://zzz/aaa
http://zzz/bbb