Cukup sering ketika bekerja dengan file teks Anda harus menemukan dan mengganti string teks dalam satu file atau lebih.

sed adalah singkatan dari stream editor. Perintah sed dapat melakukan manipulasi teks dasar pada file dan input stream seperti pipe. Dengan sed, Anda dapat mencari, menemukan dan mengganti, menyisipkan, dan menghapus per kata maupun per baris. Ini mendukung regular expressions dasar maupun lanjutan yang memungkinkan Anda untuk mencocokkan pola yang kompleks.

Di artikel ini, kita akan berbicara tentang bagaimana menemukan dan mengganti string dengan sed. Kami juga akan menunjukkan kepada Anda bagaimana melakukan pencarian dan penggantian secara rekursif.

Cara Mencari dan Mengganti String dengan sed

Ada beberapa versi sed, dengan beberapa perbedaan fungsional di antara mereka. macOS menggunakan versi BSD dan sebagian besar distribusi Linux datang dengan GNU dan telah di instal secara default. Untuk contoh kasus dalam artikel ini, Kami akan menggunakan versi GNU.

Bentuk umum search and replace  teks menggunakan sed mengambil bentuk berikut:

sed -i 's/SEARCH_REGEX/REPLACEMENT/g' INPUTFILE
  • -i – Secara default sed menulis outputnya ke output standar. Opsi ini memberitahu Anda untuk mengedit file di tempat. Jika ekstensi diberikan (contohnya -i.bak) backup dari file asli akan dibuat.
  • s – Perintah subtitusi, mungkin perintah yang paling banyak digunakan di sed.
  • / / / – Karakter pembatas. Bisa berupa karakter apa saja tetapi biasanya karakter garis miring (/) digunakan.
  • SEARCH_REGEX – String normal atau regular expression untuk pencarian.
  • REPLACEMENT – String pengganti .
  • g – Flag pengganti global. Secara default, sed membaca file baris demi baris dan hanya mengubah kemunculan pertama pada SEARCH_REGEX di satu baris. Ketika flag pengganti disediakan, semua kemunculan akan diganti.
  • INPUTFILE – Nama file tempat Anda ingin menjalankan perintah.

Merupakan praktik yang baik untuk memberikan tanda kutip di argumen agar meta-karakter shell tidak akan berkembang.

Mari kita lihat contoh cara menggunakan perintah sed untuk search and replace teks dalam file dengan beberapa opsi dan flag yang paling umum digunakan.

Untuk tujuan demonstrasi, kita akan menggunakan file berikut:

nano file.txt
123 Foo foo foo 
foo /bin/bash Ubuntu foobar 456

Jika Anda menghilangkan flag g, hanya instance pertama dari string pencarian di setiap baris yang akan diganti:

sed -i 's/foo/linux/' file.txt
123 Foo linux foo 
linux /bin/bash Ubuntu foobar 456

Dengan flag pengganti global sed menggantikan semua kemunculan pola pencarian:

sed -i 's/foo/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456

Seperti yang mungkin Anda perhatikan, pada contoh sebelumnya substring foo di dalam string foobar juga diganti. Jika ini bukan perilaku yang diinginkan, gunakan ekspresi batas kata (\b) di kedua ujung string pencarian. Ini memastikan sebagian kata tidak cocok.

sed -i 's/\bfoo\b/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu foobar 456

Untuk membuat match case pola insensitive, gunakan flag I. Pada contoh di bawah ini kita menggunakan flag g dan I:

sed -i 's/foo/linux/gI' file.txt
123 linux linux linux 
linux /bin/bash Ubuntu linuxbar 456

Jika Anda ingin menemukan dan mengganti string yang berisi karakter pembatas (/), Anda harus menggunakan garis miring terbalik (\) untuk escape dari garis miring. Misalnya untuk mengganti /bin/bash dengan /usr/bin/zsh , berikut yang akan Anda gunakan

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

Opsi yang lebih mudah dan lebih mudah dibaca adalah menggunakan karakter pembatas lainnya. Kebanyakan orang menggunakan bilah vertikal (|) atau titik dua (:) . Anda juga dapat menggunakan karakter 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 dapat menggunakan regular expressions. Misalnya untuk mencari semua angka dengan 3 digit dan menggantinya dengan string number , maka perintah yang akan Anda gunakan:

sed -i 's/\b[0-9]\{3\}\b/number/g' file.txt
number Foo foo foo 
foo /bin/bash demo foobar number

Fitur lain yang berguna dari sed adalah Anda dapat menggunakan karakter ampersand & yang sesuai dengan pola yang cocok. Karakter dapat digunakan beberapa kali.

Misalnya, jika Anda ingin menambahkan kurung kurawal {} di sekitar setiap 3 digit angka, ketik:

sed -i 's/\b[0-9]\{3\}\b/{&}/g' file.txt
{123} Foo foo foo 
foo /bin/bash demo foobar {456}

Terakhir namun tidak kalah pentingnya, selalu merupakan ide bagus untuk membuat cadangan saat mengedit file dengan sed. Untuk melakukan itu cukup berikan ekstensi ke opsi -i. Misalnya, untuk mengedit file.txt dan menyimpan file asli sebagai file.txt.bak yang akan Anda gunakan:

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

Jika Anda ingin memastikan bahwa backup dibuat daftar file dengan perintah ls:

ls
file.txt file.txt.bak

Kadang-kadang Anda ingin mencari direktori secara rekursif untuk file yang berisi string dan mengganti string di semua file. Ini dapat dilakukan dengan menggunakan perintah seperti find atau grep untuk secara rekursif menemukan file dalam direktori dan mem-piping nama file ke sed.

Perintah berikut ini akan secara rekursif mencari file di direktori kerja saat ini dan meneruskan nama file ke sed.

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

Untuk menghindari masalah dengan file yang mengandung spasi dalam nama mereka gunakan opsi -print0 yang memberitahu find untuk mencetak nama file, diikuti oleh karakter null dan pipe output ke sed menggunakan xargs -0:

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

Untuk mengecualikan direktori, gunakan opsi -not -path. Misalnya, jika Anda mengganti sebuah string di repo git lokal Anda untuk mengecualikan semua file yang dimulai dengan dot (.), Gunakan:

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

Jika Anda ingin mencari dan mengganti teks hanya pada file dengan ekstensi yang spesifik, maka perintah yang akan Anda gunakan:

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

Pilihan lain adalah dengan menggunakan perintah grep untuk secara rekursif menemukan semua file yang mengandung pola pencarian dan kemudian menyalurkan nama file ke sed:

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

Kesimpulan

Meskipun terlihat rumit dan kompleks pada awalnya, mencari dan mengganti teks dalam file dengan sed sangat sederhana.

Untuk mempelajari lebih lanjut tentang perintah, opsi, dan bendera, kunjungi manual GNU sed dan tutorial Grymoire.