Android

Cara menggunakan sed untuk mencari dan menggantikan rentetan dalam fail

sed: Easily replace strings across files | #7 Practical Bash

sed: Easily replace strings across files | #7 Practical Bash

Isi kandungan:

Anonim

Seringkali apabila bekerja dengan fail teks, anda perlu mencari dan mengganti rentetan teks dalam satu atau lebih fail.

sed adalah syaitan. Ia boleh melakukan manipulasi teks asas pada fail dan aliran masukan seperti saluran paip. Dengan sed anda boleh mencari, mencari dan menggantikan, menyisipkan, dan memadamkan perkataan dan baris. Ia menyokong ekspresi biasa asas dan panjang yang membolehkan anda memadankan corak kompleks.

, kami akan bercakap tentang bagaimana mencari dan menggantikan rentetan dengan sed . Kami juga akan menunjukkan kepada anda bagaimana untuk melakukan carian rekursif dan menggantikannya.

Cari dan Ganti String dengan sed

Terdapat beberapa versi sed , dengan beberapa perbezaan fungsi antara mereka. macOS menggunakan versi BSD dan kebanyakan pengedaran Linux datang dengan GNU sed sebelum dipasang secara lalai. Kami akan menggunakan versi GNU.

Bentuk umum mencari dan mengganti teks menggunakan sed mengambil bentuk berikut:

sed -i 's/SEARCH_REGEX/REPLACEMENT/g' INPUTFILE

  • -i - Secara lalai sed menulis outputnya kepada output standard. Pilihan ini memberitahu sed untuk mengedit fail di tempat. Sekiranya sambungan diberikan (ex -i.bak) sandaran fail asal akan dibuat. s - Perintah pengganti, mungkin arahan yang paling digunakan dalam sed. / / / - Perwakilan penghapus. Ia boleh menjadi watak tetapi biasanya aksara slash ( / ) digunakan. SEARCH_REGEX - Rentetan normal atau ungkapan biasa untuk dicari. REPLACEMENT - Penggantian rentetan. g - Bendera pengganti global. Secara lalai, sed membaca baris fail mengikut baris dan hanya mengubah kejadian pertama SEARCH_REGEX pada baris. Apabila bendera gantian disediakan, semua kejadian akan diganti. INPUTFILE - Nama fail di mana anda hendak menjalankan arahan.

Ia adalah amalan yang baik untuk meletakkan petikan di sekitar hujah supaya aksara meta-shell tidak akan berkembang.

Mari lihat contoh cara menggunakan perintah sed untuk mencari dan menggantikan teks dalam fail dengan beberapa pilihan dan bendera yang paling biasa digunakan.

Untuk tujuan demonstrasi, kami akan menggunakan fail berikut:

file.txt

123 Foo foo foo foo /bin/bash Ubuntu foobar 456

sed -i 's/foo/linux/' file.txt

123 Foo linux foo linux /bin/bash Ubuntu foobar 456

Dengan flag pengganti global menggantikan semua kejadian corak carian:

sed -i 's/foo/linux/g' file.txt

123 Foo linux linux linux /bin/bash Ubuntu linuxbar 456

Seperti yang mungkin anda perhatikan, dalam contoh sebelumnya substring foo di dalam tali foobar juga diganti. Jika ini bukan tingkah laku yang dikehendaki, gunakan ungkapan perbatasan perkataan ( \b ) di kedua-dua hujung rentetan carian. Ini memastikan perkataan separa tidak dipadankan.

sed -i 's/\bfoo\b/linux/g' file.txt

123 Foo linux linux linux /bin/bash Ubuntu foobar 456

Untuk membuat pola perlawanan tidak sensitif, gunakan bendera I Dalam contoh di bawah, kami menggunakan kedua-dua g dan bendera I :

sed -i 's/foo/linux/gI' file.txt

123 linux linux linux linux /bin/bash Ubuntu linuxbar 456

sed -i 's/\/bin\/bash/\/usr\/bin\/zsh/g' file.txt

Pilihan yang lebih mudah dan lebih mudah dibaca adalah menggunakan aksara pemisah yang lain. Kebanyakan orang menggunakan bar menegak ( | ) atau usus besar (:) tetapi anda boleh menggunakan watak lain:

sed -i 's|/bin/bash|/usr/bin/zsh|g' file.txt

123 Foo foo foo foo /usr/bin/zsh Ubuntu foobar 456

Anda juga boleh menggunakan ungkapan biasa. Sebagai contoh untuk mencari semua nombor 3 angka dan menggantikannya dengan number rentetan yang akan anda gunakan:

sed -i 's/\b\{3}\b/number/g' file.txt

number Foo foo foo foo /bin/bash demo foobar number

Satu lagi ciri berguna sed ialah anda boleh menggunakan aksara ampersand & yang sepadan dengan corak yang sepadan. Watak boleh digunakan beberapa kali.

Contohnya, jika anda ingin menambah pendakap kerinting {} sekitar setiap 3 digit angka, taipkan:

sed -i 's/\b\{3}\b/{&}/g' file.txt

{123} Foo foo foo foo /bin/bash demo foobar {456}

Akhir sekali, ia adalah idea yang baik untuk membuat sandaran semasa menyunting fail dengan sed . Untuk melakukan itu hanya memberikan lanjutan kepada pilihan -i . Sebagai contoh, untuk mengedit file.txt dan simpan fail asal sebagai file.txt.bak anda akan gunakan:

sed -i.bak 's/foo/linux/g' file.txt

ls

file.txt file.txt.bak

Cari dan Ganti Rekursif

Kadang-kadang anda mahu mencari direktori secara rekursif untuk fail yang mengandungi rentetan dan menggantikan rentetan dalam semua fail. Ini boleh dilakukan dengan menggunakan perintah seperti find atau grep untuk mencari fail secara rekursif dalam direktori dan memotong nama fail sed .

Perintah berikut akan mencari fail secara rekursif dalam direktori kerja semasa dan lulus nama fail sed .

find. -type f -exec sed -i 's/foo/bar/g' {} +

Untuk mengelakkan masalah dengan fail yang mengandungi ruang dalam nama mereka gunakan pilihan -print0 yang memberitahu find untuk mencetak nama fail, diikuti dengan aksara null dan paip output ke sed menggunakan xargs -0 :

find. -type f -print0 | xargs -0 sed -i 's/foo/bar/g'

Untuk mengecualikan direktori gunakan pilihan -not -path . Sebagai contoh, jika anda menggantikan rentetan dalam repo git tempatan anda untuk mengecualikan semua fail yang bermula dengan dot ( . ), Gunakan:

find. -type f -not -path '*/\.*' -print0 | xargs -0 sed -i 's/foo/bar/g'

find. -type f -name "*.md" -print0 | xargs -0 sed -i 's/foo/bar/g'

Pilihan lain adalah dengan menggunakan perintah grep untuk mencari semua fail yang mengandungi corak carian dan kemudian masukkan nama fail ke sed :

grep -rlZ 'foo'. | xargs -0 sed -i.bak 's/foo/bar/g'

Kesimpulannya

Walaupun ia mungkin kelihatan rumit dan kompleks, pada mulanya, mencari dan menggantikan teks dalam fail dengan sed adalah sangat mudah.

Untuk mengetahui lebih lanjut mengenai perintah sed , pilihan, dan bendera melawat manual GNU sed dan tutorial Grymoire sed. Jika anda mempunyai sebarang pertanyaan atau maklum balas, jangan ragu untuk meninggalkan komen.

terminal sed