Saya memiliki persyaratan dalam proyek saya untuk mengganti beberapa teks yang ada dalam file seperti foo
dengan beberapa teks lain seperti fooofoo
:
abc.txt
name
foo
foo1
Jadi saya mencoba:
sed -i "s/foo/fooofoo/g" abc.txt
Namun saya mendapatkan kesalahan ini:
sed: opsi ilegal -
i
Saya menemukan dalam manual yang harus saya gunakan:
sed -i\ "s/foo/fooofoo/g" abc.txt
Namun ini juga tidak berhasil.
Saya menemukan alternatif perl
dan awk
juga tetapi solusi di Solaris sed
akan sangat dihargai.
Saya menggunakan versi bash ini:
GNU bash, versi 3.2.57 (1) -release (sparc-sun-solaris2.10)
text-processing
sed
solaris
tpsaitwal
sumber
sumber
/usr/gnu/bin/sed
untuk mendapatkan -i dukungan.Jawaban:
Gunakan
ed
. Ini tersedia di sebagian besar platform dan dapat mengedit file Anda di tempat.Karena
sed
didasarkan padaed
sintaks untuk mengganti pola adalah serupa:sumber
ed
bukannyaex
, penasaran saja? (Saya tahu keduanya kompatibel dengan POSIX dan saya telah ditautkan ke spesifikasi.;))ex
? Untuk menjawab pertanyaan Anda: karena saya tidak pernah menggunakan,ex
saya tidak terbiasa dengannya. btw, saya telah melihat setup di manaed
ada tetapiex
tidak (tapi tidak sebaliknya) ... yang paling terkenal adalah laptop saya :)ex
perintah. Semuavi
perintah yang bisa Anda ketik yang dimulai dengan titik dua adalahex
perintah. Tentu saja ada beberapa ekstensi khusus Vim, tetapi hanya serangkaian perintah inti yang sangat kuat dan fleksibel dan banyak untuk pengeditan skrip.ex
belum dan belumed
.Jika Anda tidak dapat menginstal sed GNU, gunakan:
Ini menggunakan pengalihan untuk mengirim output sed ke file sementara. Jika sed selesai dengan sukses, maka ini menimpa
abc.txt
dengan file sementara.Seperti yang dapat dilihat dari kode sumber untuk GNU sed , inilah yang
sed -i
dilakukannya. Jadi, ini hampir seefisiensed -i
.Jika ada peluang yang
abc.tmp
sudah ada, maka Anda mungkin ingin menggunakanmktemp
atau utilitas serupa untuk menghasilkan nama unik untuk sementara.sumber
ed
, karena itu membaca seluruh file ke dalam memori.Jika Anda ingin yang setara
sed -i.bak
, itu sangat sederhana.Pertimbangkan skrip ini untuk GNU sed:
Kami cukup mengganti baris yang ditandai dengan
Ini memindahkan file yang ada menjadi cadangan, dan menulis file baru.
Jika kita ingin yang setara
maka itu sedikit lebih kompleks. Kita dapat membuka file untuk dibaca sebagai input standar, kemudian memutuskan tautannya, sebelum mengarahkan output sed untuk menggantinya:
Kami melakukan ini dalam sub-shell, sehingga stdin asli kami masih tersedia setelah ini. Dimungkinkan untuk beralih input dan beralih kembali tanpa subshell, tetapi cara ini tampaknya lebih jelas bagi saya.
Perhatikan bahwa kami berhati-hati untuk menyalin terlebih dahulu, daripada membuat
foo
file baru - ini penting jika file tersebut diketahui oleh lebih dari satu nama (yaitu memiliki tautan keras) dan Anda ingin memastikan bahwa Anda tidak memutus tautan tersebut .sumber
Pertama, Anda harus tahu bahwa
i\
perintah yang Anda maksud adalah untuk menyisipkan baris teks — bukan untuk menyimpan teks yang diedit kembali ke file. Tidak ada cara yang ditentukan POSIX untuk menggunakannyased
.Apa yang Anda bisa lakukan adalah menggunakan
ex
, yang adalah ditentukan oleh POSIX :The
x
perintah untuk "menyimpan dan keluar." Anda juga bisa menggunakanwq
tetapix
lebih pendek.The
%
tanda pada awal sarana perintah pengganti, "Terapkan perintah ini untuk setiap baris dalam buffer." Anda bisa menggunakannya1,$s/find/replace/g
juga.Satu perbedaan utama antara
ex
dansed
itused
adalah editor aliran . Ini hanya beroperasi secara berurutan, baris demi baris.ex
jauh lebih fleksibel daripada itu, dan sebenarnya Anda dapat melakukan pengeditan file teks interaktif secara langsung diex
. Ini adalah pendahulu langsung untukvi
.sumber
Menggunakan
sed
dan tidak ada file sementara yang terlihat :Anda dapat menghindari membuat "file temp" yang terlihat terpisah :
Penjelasan
Sistem mirip Unix tidak benar-benar menghapus konten file dari disk sampai keduanya tidak terhubung dalam sistem file, dan tidak terbuka dalam proses apa pun. Jadi bisa Anda lakukan
exec 3<
untuk membuka file di shell untuk membaca file deskriptor 3,rm
file (yang memutuskan tautannya dari sistem file), dan kemudian memanggilsed
dengan deskriptor file 3 yang digunakan sebagai inputnya.Perhatikan bahwa ini sangat berbeda dari ini:
Perbedaannya adalah ketika Anda melakukannya dalam satu perintah, shell hanya membuka file yang sama untuk membaca, dan untuk menulis dengan opsi untuk memotong file - karena masih file yang sama, Anda kehilangan konten. Tetapi jika Anda membukanya untuk dibaca, lalu
rm
membuka pathname yang sama untuk menulis, Anda sebenarnya membuat file baru di pathname yang sama (tetapi di lokasi inode dan disk yang baru, karena aslinya masih terbuka): jadi isinya masih tersedia.Kemudian setelah Anda selesai, Anda dapat menutup deskriptor file yang Anda buka sebelumnya (itulah yang dilakukan
exec 3<&-
sintaks khusus), yang melepaskan file asli sehingga sistem operasi dapat menghapus (menandai sebagai tidak digunakan) ruang disknya.Peringatan
Ada beberapa hal yang perlu diingat tentang solusi ini :.
Anda hanya mendapatkan satu "masuk" melalui konten - tidak ada cara portabel untuk shell untuk "mencari" kembali dalam deskriptor file - jadi setelah suatu program membaca beberapa konten, program lain hanya akan melihat sisa file. Dan
sed
akan membaca seluruh file.Ada kemungkinan kecil file asli Anda hilang jika shell / script / sed Anda terbunuh sebelum selesai.
sumber
perl -i
adalah pilihan lain yang bagus. Pertanyaannya secara khusus meminta solusi kompatibel dengan Solaris'sed
, berbeda dengan solusi denganperl
danawk
bahwa mereka disebutkan sudah menemukan. Plus, jawaban saya terutama ditujukan untuk menambahkan sesuatu yang saya pikir berguna untuk diketahui dan hilang dari jawaban lain mana pun.