sed

Substitusi teks dengan sed beserta kesadaran pengeditan in-place dan opsi -i yang aman.

Daftar isi

Mengubah teks yang sama di banyak baris sekaligus adalah pekerjaan yang tidak nyaman dilakukan secara manual. Topik ini membahas sed, yaitu stream editor yang membaca masukan baris demi baris, menerapkan perintah penyuntingan pada setiap baris, lalu mencetak hasilnya. Fokusnya adalah substitusi dengan perintah s, pemilihan baris tertentu, dan pengeditan in-place yang menulis hasil langsung ke berkas melalui opsi -i beserta kebiasaan aman yang menyertainya.

Substitusi dengan perintah s#

Seluruh contoh memakai satu berkas laporan kegiatan berisi tiga baris. Baris pertamanya memuat kata Sensor dua kali, sedangkan baris ketiga tidak memuat pola yang dicari sama sekali. Berkas itu dibuat dengan perintah berikut.

bash
# membuat berkas laporan kegiatan
printf 'Sensor aktif. Sensor mencatat suhu ruangan.\nSensor mati saat listrik padam.\nBaris ini tanpa kata yang dicari.\n' > laporan.txt
cat laporan.txt
text Keluaran
Sensor aktif. Sensor mencatat suhu ruangan.
Sensor mati saat listrik padam.
Baris ini tanpa kata yang dicari.

Bentuk dasar substitusi adalah s/pola/pengganti/. Perintah s mencari potongan baris yang cocok dengan pola, menggantinya dengan teks pengganti, dan mengulangi proses itu untuk setiap baris masukan. Baris yang tidak memuat pola tetap dicetak tanpa perubahan.

bash
# substitusi satu kemunculan per baris
sed 's/Sensor/Pendeteksi/' laporan.txt
text Keluaran
Pendeteksi aktif. Sensor mencatat suhu ruangan.
Pendeteksi mati saat listrik padam.
Baris ini tanpa kata yang dicari.

Pada keluaran di atas, baris pertama hanya kehilangan Sensor pertamanya karena perintah s secara default mengganti satu kemunculan per baris. Baris ketiga ikut tampil apa adanya karena sed mencetak setiap baris masukan, baik yang berubah maupun yang tidak. Hasil ini hanya keluaran di layar, dan bagian berikutnya membuktikan bahwa berkas aslinya tidak tersentuh.

bash
# berkas asli tidak berubah karena sed hanya membaca dan mencetak
cat laporan.txt
text Keluaran
Sensor aktif. Sensor mencatat suhu ruangan.
Sensor mati saat listrik padam.
Baris ini tanpa kata yang dicari.

Flag g dan pemilihan baris#

Dua kelengkapan yang sering dibutuhkan adalah mengganti semua kemunculan dalam satu baris dan mengganti hanya pada baris tertentu. Flag g pada akhir perintah s mengganti seluruh kemunculan, sedangkan alamat baris yang ditulis sebelum perintah membatasi baris mana yang diproses. Alamat berupa angka menunjuk nomor baris, dan alamat $ menunjuk baris terakhir.

bash
# flag g mengganti seluruh kemunculan dalam satu baris
sed 's/Sensor/Pendeteksi/g' laporan.txt
# alamat 2s membatasi substitusi pada baris kedua saja
sed '2s/mati/berhenti/' laporan.txt
text Keluaran
Pendeteksi aktif. Pendeteksi mencatat suhu ruangan.
Pendeteksi mati saat listrik padam.
Baris ini tanpa kata yang dicari.
Sensor aktif. Sensor mencatat suhu ruangan.
Sensor berhenti saat listrik padam.
Baris ini tanpa kata yang dicari.

Pada baris pertama keluaran pertama, kedua Sensor diganti sekaligus. Pada keluaran kedua, hanya baris kedua yang berubah menjadi Sensor berhenti, sedangkan baris lain tetap. Pembatas garis miring pada perintah s boleh diganti dengan karakter lain apabila pola memuat garis miring, misalnya s|lama|baru| atau s#lama#baru#.

Menahan keluaran dengan -n dan p#

Secara default sed mencetak setiap baris, sehingga baris yang tidak berubah ikut tampil. Opsi -n menahan pencetakan default itu, sedangkan flag p pada perintah s mencetak baris yang mengalami substitusi. Kombinasi keduanya menampilkan hanya baris yang berubah, mirip dengan perilaku pencarian.

bash
# opsi -n dan flag p hanya mencetak baris yang berubah
sed -n 's/Sensor/Pendeteksi/p' laporan.txt
text Keluaran
Pendeteksi aktif. Sensor mencatat suhu ruangan.
Pendeteksi mati saat listrik padam.

Dua baris pertama tampil dalam bentuk yang sudah diganti, sedangkan baris ketiga tidak tampil sama sekali karena tidak mengalami substitusi. Pola seperti ini sering dipakai untuk memeriksa baris mana yang akan terkena perubahan sebelum perubahan itu benar-benar dilakukan.

Pengeditan in-place dengan opsi -i#

Seluruh contoh sejauh ini hanya menampilkan hasil di layar. Opsi -i mengubah cara kerja sed menjadi pengeditan in-place, yaitu menulis hasil langsung ke berkas aslinya sehingga isi berkas benar-benar berganti. Opsi ini menghemat langkah, tetapi menuntut kehati-hatian karena tidak ada jalan kembali apabila pola yang ditulis keliru.

Kebiasaan tersebut dipraktikkan pada contoh berikut. Pratinjau dijalankan lebih dahulu untuk melihat baris mana yang berubah. Baru kemudian perintah yang sama diulang dengan -i untuk benar-benar mengubah berkas.

bash
# pratinjau substitusi tanpa mengubah berkas
sed 's/Sensor/Pendeteksi/g' laporan.txt
# mengubah berkas langsung setelah pratinjau sesuai
sed -i 's/Sensor/Pendeteksi/g' laporan.txt
cat laporan.txt
text Keluaran
Pendeteksi aktif. Pendeteksi mencatat suhu ruangan.
Pendeteksi mati saat listrik padam.
Baris ini tanpa kata yang dicari.
Pendeteksi aktif. Pendeteksi mencatat suhu ruangan.
Pendeteksi mati saat listrik padam.
Baris ini tanpa kata yang dicari.

Keluaran pratinjau dan isi berkas sesudah pengeditan sama persis, yang berarti pola yang dipakai sudah benar sebelum berkas disentuh. Urutan pratinjau terlebih dahulu, baru -i, adalah bentuk paling aman dari pengeditan in-place.

Apabila tetap ingin ada jalur pemulihan, GNU sed menyediakan bentuk -i dengan akhiran yang menyimpan salinan berkas asli sebelum pengeditan dilakukan. Akhiran ditulis langsung menempel pada opsi, sehingga -i.bak berarti mengubah berkas sekaligus membuat salinan berkas.bak. Contoh berikut memakai berkas piket yang baru dibuat.

bash
# membuat berkas piket sebagai contoh kedua
printf 'Senin: Ali\nSelasa: Budi\nRabu: Citra\n' > piket.txt
# opsi -i.bak menyimpan salinan sebelum mengubah berkas
sed -i.bak 's/: / - /' piket.txt
cat piket.txt
ls piket*
text Keluaran
Senin - Ali
Selasa - Budi
Rabu - Citra
piket.txt
piket.txt.bak

Berkas piket.txt.bak memuat isi sebelum perubahan, sehingga hasil pengeditan yang keliru dapat dipulihkan dengan menyalinnya kembali. Mekanisme cadangan ini merupakan kelengkapan GNU sed yang tidak selalu tersedia pada versi sed lain, sehingga keberadaannya perlu dipastikan pada sistem yang dipakai.

Kesalahan umum#

Mengira sed sudah mengubah berkas. Tanpa opsi -i, sed hanya membaca masukan dan mencetak hasilnya ke layar, sehingga perintah yang tampak berhasil belum menyentuh berkas sama sekali. Perubahan yang benar-benar diinginkan diterapkan dengan -i, idealnya setelah pratinjau cocok.

Lupa flag g. Baris yang memuat beberapa kemunculan pola hanya berubah sebagian karena s mengganti satu kemunculan per baris. Kasus ini sulit dikenali pada data besar, karena keluarannya tampak benar bagi pembaca yang tidak memeriksa seluruh barisnya. Flag g ditambahkan setiap kali satu baris boleh memuat lebih dari satu kemunculan.

Pembatas bertabrakan dengan isi pola. Garis miring pada pola mudah tertukar dengan pembatas perintah s, seperti pada s/direktori/berkas/. Pembatas boleh diganti dengan karakter lain seperti | atau #, sehingga pola yang memuat garis miring tetap terbaca jelas.

Ringkasan#

  • sed membaca masukan baris demi baris dan mencetak setiap baris, baik yang berubah maupun yang tidak, kecuali pencetakan ditahan dengan opsi -n.
  • Perintah s/pola/pengganti/ mengganti satu kemunculan per baris, flag g mengganti semuanya, dan alamat baris membatasi baris mana yang diproses.
  • Kombinasi opsi -n dan flag p menampilkan hanya baris yang berubah.
  • Opsi -i menulis hasil langsung ke berkas, dan kebiasaan amannya adalah pratinjau tanpa -i terlebih dahulu atau memakai -i.bak untuk salinan cadangan.

Referensi#