Pengeditan di tempat dengan sed pada OS X


142

Saya ingin mengedit file dengan sed pada OS X. Saya menggunakan perintah berikut:

sed 's/oldword/newword/' file.txt

Keluaran dikirim ke terminal. file.txt tidak dimodifikasi. Perubahan disimpan ke file2.txt dengan perintah ini:

sed 's/oldword/newword/' file1.txt > file2.txt

Namun saya tidak ingin file lain. Saya hanya ingin mengedit file1.txt . Bagaimana saya bisa melakukan ini?

Saya sudah mencoba flag -i. Ini menghasilkan kesalahan berikut:

sed: 1: "file1.txt": invalid command code f

2
Apa perintah tepat yang Anda gunakan saat mencoba -ibendera?
eldarerathis

Jawaban:


282

Anda dapat menggunakan -iflag dengan benar dengan memberikan suffix untuk ditambahkan ke file yang dicadangkan. Memperluas contoh Anda:

sed -i.bu 's/oldword/newword/' file1.txt

Akan memberi Anda dua file: satu dengan nama file1.txtyang berisi substitusi, dan satu dengan nama file1.txt.buyang memiliki konten asli.

Agak berbahaya

Jika Anda ingin menimpa file asli secara destruktif, gunakan sesuatu seperti:

sed -i '' 's/oldword/newword/' file1.txt
      ^ note the space

Karena cara garis diuraikan, diperlukan spasi antara flag opsi dan argumennya karena argumennya panjang nol.

Selain mungkin merusak sumber asli Anda, saya tidak mengetahui ada bahaya lebih lanjut dari menipu dengan cara ini. Namun perlu dicatat bahwa jika permohonan sedini merupakan bagian dari skrip, The Unix Way ™ akan menggunakan ( sednon-destruktif), menguji apakah itu keluar dengan bersih, dan hanya kemudian menghapus file asing.


Anda benar saya menghilangkan ekstensi setelah bendera -i. Apakah -i''berbahaya karena alasan apa pun selain berpotensi mengacaukan file asli (dan tidak memiliki cadangan)?
SundayMonday

Menurut sedhalaman manual jika Anda kehabisan ruang disk pada perangkat Anda dapat merusak file saat sedang berjalan dan memiliki hasil output yang buruk. Jika Anda bekerja di bawah kendali sumber lokal sed -i ""tanpa cadangan, sebagian besar waktu akan baik-baik saja (atau sesaat git init && git add -A . && git commit -m 'backup'sebelum menjalankan -imode sed ).
cfeduke

2
Saya menemukan sedikit agak berbahaya sangat berguna. +1
Andre

5
BSD sed mensyaratkan bahwa tidak ada ruang setelah flag -i. Jadi, -i''ini valid, tetapi -i ''tidak.
Todd A. Jacobs

3
Argh! BSD sed mengabaikan karakter '\ n' dan mencetak 'n' sebagai gantinya! Saya hanya akan mengganti BSD sed dengan GNU sed di mac saya!
nterry

20

Saya punya masalah serupa dengan MacOS

sed -i '' 's/oldword/newword/' file1.txt

tidak berhasil, tapi

sed -i"any_symbol" 's/oldword/newword/' file1.txt

bekerja dengan baik.


Ini sekarang sebaliknya. sed -i '' <file>bekerja tetapi sed -i'' <file>tidak lagi berfungsi
Zohaib Amanzai


4

Anda dapat menggunakan -i''( --in-place) untuk sedseperti yang disarankan. Lihat: The -idi tempat argumen , namun perhatikan bahwa -ipilihan adalah ekstensi FreeBSD non-standar dan mungkin tidak tersedia pada sistem operasi lain. Kedua sedadalah S tream ED itor, bukan file editor .


Cara alternatif adalah dengan menggunakan substitusi bawaan dalam mode Vim Ex, seperti:

$ ex +%s/foo/bar/g -scwq file.txt

dan untuk banyak file:

$ ex +'bufdo!%s/foo/bar/g' -scxa *.*

Untuk mengedit semua file secara rekursif, Anda dapat menggunakan **/*.*jika shell mendukungnya (diaktifkan oleh shopt -s globstar).


Cara lain adalah dengan menggunakan gawkdan ekstensi "inplace" yang baru seperti:

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1

4

Ini menciptakan file cadangan. Misalnya sed -i -e 's/hello/hello world/' testfileuntuk saya, buat file cadangan, testfile-e, di dir yang sama.


Sama di sini dengan Mac OS Catalina. Melewati kedua -i dan -e secara terpisah (TIDAK -selama!) Membuat file cadangan dengan '-e' ditambahkan.
Daniel Kesner

1

Kamu bisa memakai:

sed -i -e 's/<string-to-find>/<string-to-replace>/' <your-file-path>

Contoh:

sed -i -e 's/Hello/Bye/' file.txt

Ini berfungsi sempurna di Mac .


2
Ini membuat file cadangan untuk saya di Mac OS Catalina dengan '-e' ditambahkan.
Daniel Kesner

Ini salah untuk macOS. Silakan lihat halaman "man sed" di sana. -imembutuhkan argumen untuk macOS. Karena Anda tidak menentukan satu, itu menggunakan -e, yang menghasilkan memiliki file kedua dengan -editambahkan. -etidak ada di macOS, itu -E. Jadi perintah yang benar untuk macOS adalahsed -i '' -E 's/Hello/Bye/' file.txt
Marc J. Schmidt
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.