Ganti string dengan konten file menggunakan sed

23

Saya punya dua file berbeda:

File1

/home/user1/  
/home/user2/bin  
/home/user1/a/b/c

File2

<TEXT1>
<TEXT2>

Saya ingin mengganti <TEXT1>dari File2 dengan isi File1 menggunakan sed. Saya mencoba perintah ini, tetapi tidak mendapatkan output yang tepat:

cat File2|sed "s/<TEXT1>/$(cat File1|sed 's/\//\\\//g'|sed 's/$/\\n/g'|tr -d "\n")/g"

Anda dapat menggunakan alat lain juga untuk menyelesaikan masalah ini.

chanchal1987
sumber
Harap tempel pesan kesalahan itu sehingga kami dapat menemukan sumbernya. Beri tahu kami sedimplementasi mana yang Anda gunakan. Kode Anda berfungsi untuk saya dengan GNU sed.
manatwork
Maaf, tidak mendapatkan kesalahan. Saya tidak mendapatkan hasil yang diinginkan. Outputnya seperti /home/user1/ n/home/user2/bin n/home/user1/a/b/cn <TEXT2>. Tidak mendapat baris baru.
chanchal1987
Tidak yakin apakah ini akan berlaku dalam kasus spesifik Anda, tetapi dengan diffdan patchalat memungkinkan untuk mengganti beberapa baris dalam file dengan baris lain dengan cukup mudah.
Stéphane Gimenez
1
Btw, menggunakan data acak yang dikumpulkan dengan $()skrip sed membuat mata saya berdarah. Jangan pernah menggunakan data eksternal di tempat-tempat di mana beberapa karakter ditafsirkan dengan makna khusus.
Stéphane Gimenez
Pertanyaan serupa: Pola pengganti dalam file dengan konten file lain
Toby Speight

Jawaban:

24

Inilah solusi skrip sed (lebih mudah dilihat daripada mencoba membuatnya menjadi satu baris pada baris perintah):

/<TEXT1>/ {
  r File1
  d
}

Menjalankannya:

$ sed -f script.sed File2
/home/user1/
/home/user2/bin
/home/user1/a/b/c
<TEXT2>
Kusalananda
sumber
Terima kasih ini berfungsi. Tetapi saya tidak ingin menggunakan file skrip lainnya. Apakah ada solusi sebaris?
chanchal1987
Tentu:, di sed '/<TEXT1>/{rFile1^Md^M}' File2mana "^ M" Anda menekan kembali. Masalahnya adalah sed benar-benar membutuhkan baris baru di dalam {...} untuk membatasi perintah r dan d.
Kusalananda
6
dengan bash, string gaya posix sedikit lebih bersih:sed $'/<TEXT1>/ {r File1\n d}'
glenn jackman
9
Juga dengan -e untuk satu liner:sed -e '/<TEXT1>/{r File1' -e 'd}' File2
sdaau
1
Dan bagaimana jika alih-alih mengganti seluruh baris yang berisi <TEXT1>, saya hanya ingin mengganti string itu sendiri, meninggalkan sisa garis utuh? Text1: <TEXT1>untuk Text1: <file_contents>.
Robin Winslow
9

Butuh waktu lama untuk menemukan solusi ini menggunakan penggantian var. Semua solusi sed tidak bekerja untuk saya, karena mereka menghapus baris lengkap atau mengganti secara tidak benar.

FILE2=$(<file2)
FILE1=$(<file1)
echo "${FILE2//TEXT1/$FILE1}" 

Mengganti semua kejadian TEXT1 dalam file2 terhadap konten file1. Semua teks lainnya tetap tidak tersentuh.

marcas756
sumber
sangat bagus. mungkin lebih cepat daripada sedterlalu, karena "ekspansi" (alias penggantian) dibangun ke dalam shell ( bashsetidaknya)
kuning
7

Saya menjawab karena metode diff/ patchmungkin menarik dalam beberapa kasus. Untuk menentukan substitusi baris yang terkandung dalam file blob1dengan baris yang terkandung dalam blob2penggunaan:

diff -u blob1 blob2 > patch-file

Misalnya, jika blob1mengandung:

hello
you

dan blob2mengandung:

be
welcome
here

yang dihasilkan patch-fileadalah:

--- blob1   2011-09-08 16:42:24.000000000 +0200
+++ blob2   2011-09-08 16:50:48.000000000 +0200
@@ -1,2 +1,3 @@
-hello
-you
+be
+welcome
+here

Sekarang, Anda dapat menerapkan tambalan ini ke file lain:

patch somefile patch-file

Ini akan menggantikan hello, yougaris dengan be, welcome, herebaris dalam somefile.

Stéphane Gimenez
sumber
ini sangat pintar tetapi akan lebih baik jika Anda bisa mengotomatiskannya dalam skrip
qodeninja