วิธีการแทนที่ส่วนของไฟล์ข้อความระหว่างเครื่องหมายด้วยไฟล์ข้อความอื่นได้อย่างไร


26

ว่าฉันมีไฟล์ข้อความเช่นนี้:

# custom content section
a
b

### BEGIN GENERATED CONTENT
c
d
### END GENERATED CONTENT

ฉันต้องการแทนที่ส่วนระหว่างGENERATED CONTENTแท็กด้วยเนื้อหาของไฟล์อื่น

วิธีที่ง่ายที่สุดในการทำเช่นนี้คืออะไร?

คำตอบ:


36
lead='^### BEGIN GENERATED CONTENT$'
tail='^### END GENERATED CONTENT$'
sed -e "/$lead/,/$tail/{ /$lead/{p; r insert_file
        }; /$tail/p; d }"  existing_file

ยอดเยี่ยม sedสามารถทำได้มากกว่าเพียงแค่s/.../...!
DevSolar

อืมฉันไม่ได้ผลสำหรับฉันฉันควรจะใส่คำสั่ง sed ในหนึ่งบรรทัด?
lzap

3
r insert_fileคำสั่งจะต้องเป็นสิ่งสุดท้ายในสายของ โปรดทราบว่าไม่อนุญาตให้มีช่องว่างหรือความคิดเห็น รหัสได้รับการทดสอบโดยใช้ GNU sedโดย--posixเปิดใช้งานตัวเลือกและทำงานได้ตามที่คาดไว้ดังนั้นจึงควรทำงานกับPOSIX ที่เข้ากัน sedได้
Peter.O

1
moly ศักดิ์สิทธิ์นั่นเจ๋ง! นี่กำลังจะเกิดขึ้นในพจนานุกรมของฉัน! มีประโยชน์อย่างมากและเรียบง่ายสวยงาม ขอขอบคุณ!
DanielSmedegaardBuus

2
โปรดทราบว่าการแก้ไขในสถานที่คุณต้องใช้เอาต์พุตของ sed (เช่นoutput=$(sed -e "..." existing_file)) จากนั้นทำการแทนที่เป็นครั้งที่สอง (เช่นecho "$output" > existing_file) เนื่องจากการพยายามเปลี่ยนเส้นทางไปยังไฟล์ที่คุณกำลังอ่านจะทำให้การตัดทอนก่อนที่จะอ่านเนื้อหา
Chris Tonkinson


4

คำเตือน: นี่ไม่ใช่วิธีที่ง่ายที่สุดที่จะทำ (แก้ไข: ทุบตีทำงาน; POSIX grep ก็ใช้ได้เช่นกัน)

หากข้อความหลักอยู่ในไฟล์ "main" และเนื้อหาที่สร้างขึ้นอยู่ในไฟล์ "gen" คุณสามารถทำสิ่งต่อไปนี้:

#!/bin/bash
BEGIN_GEN=$(cat main | grep -n '### BEGIN GENERATED CONTENT' | sed 's/\(.*\):.*/\1/g')
END_GEN=$(cat main | grep -n '### END GENERATED CONTENT' | sed 's/\(.*\):.*/\1/g')
cat <(head -n $(expr $BEGIN_GEN - 1) main) gen <(tail -n +$(expr $END_GEN + 1) main) >temp
mv temp main

มันใช้ได้ไหม? ฉันคิดว่าบรรทัดสุดท้ายของคุณจะเปิดmainให้เขียนล้างก่อนที่แมวจะอ่าน
chepner

@chepner Crap คุณพูดถูก ส่วนที่เหลือใช้งานได้แม้ว่า ฉันจะแก้ไข
ดรคิตตี้

3
ed -s FILE1 <<EOF
/### BEGIN GENERATED/+,/### END GENERATED/-d
/### BEGIN GENERATED/ r FILE2
w
q
EOF

การใช้ heredoc และ ed line editor บรรทัดแรกใน heredoc คือการลบ 'd' บรรทัดหลัง '+' the '### BEGIN GENERATED ... ' และบรรทัดก่อน '-' the '### END สร้างแล้ว ... ' บรรทัดที่สอง คือการแทรก FILE2 หลังจากบรรทัด ### END สร้างแล้ว ... '
Jetchisel

ขออภัยสิ่งที่ฉันหมายถึงคือแทรก FILE2 หลังจากบรรทัด '### BEGIN GENERATED .. '
Jetchisel

ใช้ง่ายกับฉันคนมันเป็นหลังจากครั้งแรกของฉัน :-) นอกจากนี้ฉันอาจใช้คำเดียวกัน แต่โซลูชันอื่นไม่ได้ใช้ heredocs แต่ printf และไปป์ ทางใดทางหนึ่งถ้าฉันทำผิด :-)
Jetchisel

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