Bagaimana cara mengganti bagian dari file teks antara marker dengan file teks lain?

26

Katakanlah saya memiliki file teks seperti ini:

# custom content section
a
b

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

Saya ingin mengganti bagian antara GENERATED CONTENTtag dengan konten file lain.

Apa cara paling sederhana untuk melakukan ini?

smokris
sumber

Jawaban:

36
lead='^### BEGIN GENERATED CONTENT$'
tail='^### END GENERATED CONTENT$'
sed -e "/$lead/,/$tail/{ /$lead/{p; r insert_file
        }; /$tail/p; d }"  existing_file
Peter.O
sumber
Luar biasa. seddapat melakukan lebih dari sekadar s/.../...!
DevSolar
Hmmm tidak bekerja untuk saya, haruskah saya menempatkan perintah sed pada satu baris?
lzap
3
The r insert_fileperintah harus menjadi hal terakhir pada baris. Perhatikan bahwa spasi putih atau komentar tidak diizinkan setelahnya. Kode diuji menggunakan GNU seddengan --posixopsi yang diaktifkan, dan itu berfungsi seperti yang diharapkan, jadi itu harus bekerja dengan setiap posix compliant sed .
Peter.O
1
Astaga, itu keren! Ini masuk dalam kamus sed saya! Sangat berguna dan sangat sederhana. Terima kasih!
DanielSmedegaardBuus
2
Catatan pengeditan di tempat mengharuskan Anda menangkap output sed (mis output=$(sed -e "..." existing_file)) dan kemudian melakukan penggantian dalam pass kedua (mis. echo "$output" > existing_file) Karena mencoba mengalihkan ke file yang Anda baca akan menyebabkannya terpotong sebelum konten dibaca.
Chris Tonkinson
5
newContent=`cat new_file`
perl -0777 -i -pe "s/(### BEGIN GENERATED CONTENT\\n).*(\\n### END GENERATED CONTENT)/\$1$newContent\$2/s" existing_file
smokris
sumber
Pekerjaan yang baik. Jauh lebih sederhana dari milikku. :)
Dr Kitty
4

Peringatan: Ini jelas bukan cara paling sederhana untuk melakukannya. (EDIT: bash berfungsi; POSIX grep juga baik-baik saja)

Jika teks utama di file "main" dan konten yang dihasilkan di file "gen", Anda bisa melakukan hal berikut:

#!/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
Dr Kitty
sumber
Apakah ini berhasil? Saya pikir baris terakhir Anda akan terbuka mainuntuk menulis, membersihkannya, sebelum dibaca oleh kucing.
chepner
@ chepner Crap, kau benar. Tapi sisanya tetap bekerja. Saya akan memperbaikinya.
Dr Kitty
3
ed -s FILE1 <<EOF
/### BEGIN GENERATED/+,/### END GENERATED/-d
/### BEGIN GENERATED/ r FILE2
w
q
EOF
Jetchisel
sumber
Menggunakan heredoc dan editor baris ed. Baris pertama di dalam heredoc adalah menghapus 'd' baris setelah '+' the '### BEGIN GENERATED ...' dan baris sebelum '-' the '### END GENERATED ...' baris kedua adalah memasukkan FILE2 setelah baris ### END GENERATED ... '
Jetchisel
maaf yang saya maksud adalah memasukkan FILE2 setelah baris '### BEGIN GENERATED ..'
Jetchisel
Tenang saja, kawan, ini pertama kalinya saya :-). Juga saya mungkin menggunakan kata yang sama tetapi solusi lain tidak menggunakan heredocs tetapi printf dan pipa.
Mohon
Terima kasih, sangat mudah dibaca! Btw - bukannya r FILE2Anda bisa mengatakan r !commanduntuk membaca dari skrip yang berbeda.
Kos