Apakah ada permintaan untuk sed
melakukan pengeditan di tempat tanpa cadangan yang berfungsi baik di Linux dan Mac? Sementara BSD yang sed
dikirimkan dengan OS X tampaknya diperlukan sed -i '' …
, sed
distribusi GNU Linux biasanya datang dengan menafsirkan kutipan sebagai nama file input kosong (bukan ekstensi cadangan), dan sed -i …
sebagai gantinya perlu .
Apakah ada sintaks baris perintah yang berfungsi dengan kedua rasa, sehingga saya dapat menggunakan skrip yang sama pada kedua sistem?
Jawaban:
Jika Anda benar-benar hanya ingin menggunakan
sed -i
cara 'mudah', berikut ini TIDAK berfungsi pada GNU dan BSD / Macsed
:Perhatikan kurangnya ruang dan titik.
Bukti:
Jelas Anda kemudian bisa menghapus
.bak
file.sumber
sed
)sed
tidak menerimacommand
argumen posisi ketika dipanggil-i
- harus dilengkapi dengan flag lain-e
,. Dengan demikian, perintahnya menjadi:sed -i.bak -e 's/foo/bar/' filename
sed -i.bak 's/foo/bar/' file && rm file.bak
Ini berfungsi dengan GNU sed, tetapi tidak pada OS X:
Ini berfungsi pada OS X, tetapi tidak dengan GNU sed:
Di OS X Anda
sed -i -e
karena ekstensi file cadangan akan diatur ke-e
sed -i'' -e
karena alasan yang sama — ia membutuhkan ruang antara-i
dan''
.sumber
-i
dan-i''
identik pada waktu penguraian shell;sed
tidak bisa berperilaku berbeda pada dua doa pertama, karena mendapat argumen yang sama persis.Ketika di OSX, saya selalu menginstal versi sed GNU melalui Homebrew, untuk menghindari masalah dalam skrip, karena sebagian besar skrip ditulis untuk versi sed GNU.
Kemudian sed BSD Anda akan digantikan oleh GNU sed.
Atau, Anda dapat menginstal tanpa nama default, tetapi kemudian:
PATH
sesuai petunjuk setelah menginstalgnu-sed
gsed
ataused
tergantung pada sistem Andasumber
--with-default-names
telah dihapus dari homebrew-core , info lebih lanjut di ini jawaban. ketika menginstalgnu-sed
sekarang, petunjuk instalasi menentukan bahwa Anda perlu menambahkangnubin
kePATH
:PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
Seperti yang ditanyakan oleh Noufal Ibrahim , mengapa Anda tidak bisa menggunakan Perl? Setiap Mac akan memiliki Perl, dan ada sangat sedikit distribusi Linux atau BSD yang tidak menyertakan beberapa versi Perl dalam sistem basis. Satu-satunya lingkungan yang mungkin benar-benar kekurangan Perl adalah BusyBox (yang berfungsi seperti GNU / Linux
-i
, kecuali tidak ada ekstensi cadangan yang dapat ditentukan).Seperti yang direkomendasikan ismail ,
dan ini sepertinya solusi yang lebih baik dalam hampir semua kasus daripada skrip, alias, atau solusi lain untuk menangani ketidakcocokan mendasar
sed -i
antara GNU / Linux dan BSD / Mac.sumber
perl
adalah bagian dari spesifikasi Basis Standar Linux sejak 1 Mei 2009. refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Languages/…Tidak ada cara untuk membuatnya bekerja.
Salah satu caranya adalah dengan menggunakan file sementara seperti:
Ini bekerja pada keduanya
sumber
Jawab: Tidak.
Jawaban yang semula diterima sebenarnya tidak melakukan apa yang diminta (sebagaimana disebutkan dalam komentar). (Saya menemukan jawaban ini ketika mencari alasan a
file-e
muncul "secara acak" di direktori saya.)Tampaknya tidak ada cara
sed -i
untuk bekerja secara konsisten pada MacOS dan Linuces.Rekomendasi saya, untuk apa nilainya, bukan untuk memperbarui di tempat dengan
sed
(yang memiliki mode kegagalan yang kompleks), tetapi untuk menghasilkan file baru dan mengganti nama mereka sesudahnya. Dengan kata lain: hindari-i
.sumber
The
-i
pilihan adalah bukan bagian dari POSIX Sed . Metode yang lebih portabel adalah menggunakan Vim dalam mode Ex:%
pilih semua bariss
menggantikanx
Simpan dan tutupsumber
Berikut ini versi lain yang berfungsi di Linux dan macOS tanpa menggunakan
eval
dan tanpa harus menghapus file cadangan. Ini menggunakan array Bash untuk menyimpansed
parameter, yang lebih bersih daripada menggunakaneval
:Ini tidak membuat file cadangan, juga file dengan kutipan yang ditambahkan.
sumber
sedi=(-i) && [ "$(uname)" == "Darwin" ] && sedi=(-i '')
sed "${sedi[@]}" -e 's/foo/bar/' target.file
Jawaban Steve Powell cukup benar, merujuk pada halaman MAN untuk OSX dan Linux (Ubuntu 12.04) menyoroti ketidakcocokan dalam penggunaan 'in-place' di kedua sistem operasi.
JFYI, seharusnya tidak ada ruang antara -i dan tanda kutip (yang menunjukkan ekstensi file kosong) menggunakan versi sed Linux, sehingga
sed Linux Man Page
dan
sed halaman OSX Man
Saya menyelesaikan ini dalam skrip dengan menggunakan perintah alias'd dan output nama OS dari ' uname ' dalam bash 'jika'. Mencoba menyimpan string perintah yang bergantung pada OS dalam variabel tidak dapat dilakukan ketika menafsirkan kutipan. Penggunaan ' shopt -s expand_aliases ' diperlukan untuk mengembangkan / menggunakan alias yang didefinisikan dalam skrip Anda. Penggunaan shopt dibahas di sini .
sumber
Jika Anda perlu melakukan
sed
in-place dalambash
skrip, dan Anda TIDAK ingin in-place dihasilkan dengan file .bkp, dan Anda memiliki cara untuk mendeteksi os (katakanlah, menggunakan ostype.sh ), - maka hack berikut denganbash
shell built-ineval
harus bekerja:sumber
Anda bisa menggunakan spons. Sponge adalah program unix lama, ditemukan dalam paket moreutils (baik di ubuntu dan mungkin debian, dan di homebrew di mac).
Ini akan buffer semua konten dari pipa, tunggu sampai pipa dekat (mungkin berarti bahwa file input sudah tutup) dan kemudian timpa:
Dari halaman manual :
sumber
Berikut ini berfungsi untuk saya di Linux dan OS X:
sed -i' ' <expr> <file>
misal untuk file yang
f
berisiaaabbaaba
sed -i' ' 's/b/c/g' f
hasil
aaaccaaca
pada Linux dan Mac. Perhatikan ada string yang dikutip berisi spasi , tanpa spasi di antara-i
dan. Kutipan tunggal atau ganda keduanya berfungsi.Di Linux saya menggunakan
bash
versi 4.3.11 di Ubuntu 14.04.4 dan di Mac versi 3.2.57 di OS X 10.11.4 El Capitan (Darwin 15.4.0).sumber
Saya mengalami masalah ini. Satu-satunya solusi cepat adalah mengganti sed di mac ke versi gnu:
sumber