Saya sedang menulis skrip shell untuk server saya, yang merupakan shared hosting yang menjalankan FreeBSD. Saya juga ingin dapat mengujinya secara lokal, di PC saya yang menjalankan Linux. Oleh karena itu, saya mencoba menulisnya dengan cara portabel, tetapi dengan sed
Saya tidak melihat cara untuk melakukan itu.
Bagian dari situs web saya menggunakan file HTML statis yang dihasilkan, dan baris sed ini menyisipkan DOCTYPE yang benar setelah setiap regenerasi:
sed -i '1s/^/<!DOCTYPE html> n/' ${file_name.html}
Ia bekerja dengan GNU sed
di Linux, tapi FreeBSD sed
mengharapkan argumen pertama setelah -i
pilihan untuk menjadi ekstensi untuk salinan cadangan. Ini akan terlihat seperti:
sed -i '' '1s/^/<!DOCTYPE html> n/' ${file_name.html}
Namun, GNU sed
sebaliknya mengharapkan ekspresi mengikuti segera setelah -i
.
(Ini juga memerlukan perbaikan dengan penanganan baris baru, tapi itu sudah dijawab di sini)
Tentu saja saya dapat memasukkan perubahan ini dalam salinan skrip server saya, tetapi itu akan mengacaukan penggunaan VCS saya untuk pembuatan versi. Apakah ada cara untuk mencapai ini dengan sed dengan cara yang sepenuhnya portabel?
Jawaban yang Diterima:
GNU sed menerima ekstensi opsional setelah -i
. Ekstensi harus dalam argumen yang sama tanpa spasi. Sintaks ini juga berfungsi pada sed BSD.
sed -i.bak -e '…' SOMEFILE
Perhatikan bahwa pada BSD, -i
juga mengubah perilaku ketika ada beberapa file input:mereka diproses secara independen (jadi misalnya $
cocok dengan baris terakhir setiap file). Ini juga tidak akan berfungsi di BusyBox.
Jika Anda tidak ingin menggunakan file cadangan, Anda dapat memeriksa versi sed yang tersedia.
case $(sed --help 2>&1) in
*GNU*) set sed -i;;
*) set sed -i '';;
esac
"[email protected]" -e '…' "$file"
Atau sebagai alternatif, untuk menghindari mengganggu parameter posisi, definisikan sebuah fungsi.
case $(sed --help 2>&1) in
*GNU*) sed_i () { sed -i "[email protected]"; };;
*) sed_i () { sed -i '' "[email protected]"; };;
esac
sed_i -e '…' "$file"
Jika Anda tidak ingin repot, gunakan Perl.
perl -i -pe '…' "$file"
Jika Anda ingin menulis skrip portabel, jangan gunakan -i
— tidak ada di POSIX. Lakukan secara manual apa yang dilakukan sed di balik layar — hanya satu baris kode lagi.
sed -e '…' "$file" >"$file.new"
mv -- "$file.new" "$file"