GNU/Linux >> Belajar Linux >  >> Linux

Memulai Dengan Perintah SED [Panduan Pemula]

Sed adalah bagian dari kotak peralatan standar Unix sejak akhir tahun 60-an. Seperti editor teks lainnya, ini akan membantu Anda untuk memodifikasi file teks. Namun, bertentangan dengan editor teks yang mungkin telah Anda gunakan, ini adalah editor non-interaktif.

Artinya, Anda menentukan terlebih dahulu transformasi yang ingin diterapkan ke file, lalu alat tersebut dapat menerapkan transformasi tersebut tanpa pengawasan.

Deskripsi terbaik dari tujuan desain alat ini berasal dari Lee E. McMahon, pengembang inti dari implementasi asli dalam makalah aslinya:

Sed adalah editor konteks non-interaktif yang berjalan pada sistem operasi UNIX. Sed dirancang untuk sangat berguna dalam tiga kasus:

  1. Untuk mengedit file yang terlalu besar untuk pengeditan interaktif yang nyaman;
  2. Untuk mengedit file ukuran apa pun ketika urutan perintah pengeditan terlalu rumit untuk diketik dengan nyaman dalam mode interaktif.
  3. Untuk melakukan beberapa fungsi pengeditan `global' secara efisien dalam satu masukan.

Desain tujuan (1) dan (3) mungkin kurang relevan dengan perangkat keras modern kita, tetapi yang kedua tetap valid. Sebagai tambahan pribadi, menurut saya sed sangat cocok untuk tugas yang berulang seperti saat Anda ingin menerapkan transformasi yang sama ke sekumpulan file.

Pelajari perintah SED dasar dengan contoh-contoh ini

Untuk memberi Anda gambaran tentang kekuatan di balik sed, saya akan mempertimbangkan kasus pengembang yang perlu menambahkan header lisensi di atas setiap file sumber dalam proyeknya:

[email protected]:~$ head MIT.LICENSE *.sh
==> MIT.LICENSE <==
-----8<----------------------------------------------------------------
Copyright <YEAR> <COPYRIGHT HOLDER>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

==> script1.sh <==
#!/bin/bash

echo Hello, I\'m the first script

==> script2.sh <==
#!/bin/bash

cat << EOF
Hello, I'm the second script
EOF

Saya tidak hanya ingin melihat file lisensi di atas setiap skrip shell, tetapi saya juga ingin tahun dan tempat penampung hak cipta diganti dengan nilai sebenarnya. Itu akan menjadi kasus penggunaan pertama kami.

Catatan:jika Anda ingin berlatih sendiri, Anda dapat mengunduh file sampel dari situs web saya. Anda mungkin juga ingin melihat video yang melengkapi artikel ini:

1. Mengganti teks dalam SED

Dalam file lisensi saya, saya ingin mengganti placeholder dan dengan nilai sebenarnya.

Ini adalah pekerjaan yang sangat cocok untuk sed substitusi memerintah. Mungkin yang paling berguna dari semua perintah sed:

[email protected]:~$ sed -e 's/<YEAR>/2018/' MIT.LICENSE  | head -5
-----8<----------------------------------------------------------------
Copyright 2018 <COPYRIGHT HOLDER>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

Menggunakan pipa (| ), saya meneruskan output dari perintah sed ke head alat untuk menampilkan hanya lima baris pertama di sini. Namun, untuk topik khusus kita hari ini, bagian yang paling menarik adalah s/<YEAR>/2018/ ekspresi.

Sed bekerja dengan memproses file input satu per satu. Pada setiap baris, pengganti (s ) perintah akan menggantikan kemunculan pertama teks di antara dua garis miring pertama (/<YEAR>/ ) dengan teks di antara dua yang terakhir (/2018/ ). Anggap saja seperti fitur cari-ganti yang Anda miliki di editor teks GUI.

Perlu disebutkan di sini, file MIT.LICENSE asli tidak dimodifikasi. Saya membiarkan Anda memeriksanya sendiri menggunakan perintah berikut:

head -5 MIT.LICENSE

2. Mengganti teks… lagi

Hebat:kami telah mengganti placeholder tahun. Tapi ada yang kedua untuk menggantikan. Jika Anda memahami contoh sebelumnya, Anda mungkin dapat membayangkan ekspresi sed kedua seperti ini:

's/<COPYRIGHT HOLDER>/Sylvain Leroux/'

Tapi di mana menempatkan itu? Nah, Anda memiliki beberapa pilihan. Yang paling jelas jika Anda sudah familiar dengan konsep redirection adalah untuk menyalurkan output dari perintah sed pertama kita ke instance kedua dari sed:

[email protected]:~$ sed -e 's/<YEAR>/2018/' MIT.LICENSE  |
    sed -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' |
    head -5
----8<----------------------------------------------------------------
Copyright 2018 Sylvain Leroux

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

Tapi kami bisa lebih baik. Sejak -e opsi memperkenalkan ekspresi sed, kita dapat menggunakan beberapa di antaranya sebagai bagian dari pemanggilan sed yang sama, dan hasilnya akan sama:

# Pay special attention to the \ at the end of the lines
# specifying the *same* command continues on the
# next line:
sh$ sed -e 's/<YEAR>/2018/'  \
                -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
                MIT.LICENSE |
        head -5

Terakhir, Anda juga dapat menentukan beberapa perintah dalam ekspresi sed yang sama dengan memisahkannya dengan baris baru. Ini sangat berguna ketika Anda mulai menulis program sed yang lebih kompleks:

# Pay special attention to the single-quotes and
# backslash placement:
sh$ sed -e 's/<YEAR>/2018/
            s/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        MIT.LICENSE |
    head -5

3. Menyisipkan teks

Sekarang kami telah mengganti placeholder dengan nilai sebenarnya. Tetapi kami masih memiliki beberapa pekerjaan yang harus dilakukan sebelum dapat memasukkan file lisensi itu ke dalam file proyek. Yang kemudian menjadi skrip shell, setiap baris lisensi harus dimulai dengan octothorp (# ) agar shell dapat memahaminya, shell tidak boleh mencoba menafsirkan baris-baris tersebut.

Untuk itu, kita akan menggunakan perintah substitusi lagi. Sesuatu yang tidak saya sebutkan sebelumnya adalah, bertentangan dengan sebagian besar fitur pencarian-ganti editor GUI, pola pencarian belum tentu string literal untuk dicari. Sebenarnya, ini adalah ekspresi reguler (regex). Artinya, selain karakter biasa yang akan cocok dengan kata demi kata, Anda dapat menggunakan karakter yang akan memiliki arti khusus. Misalnya, tanda sisipan (^ ) mewakili awal baris, tanda dolar ($ ) akhir baris, atau, sebagai contoh terakhir, bintang titik (.* ) berarti setiap urutan 0, 1 atau beberapa karakter. Ada banyak metakarakter lain seperti itu, tetapi untuk saat ini, ini sudah lebih dari cukup.

Jadi untuk masukkan beberapa teks di awal baris, pilihannya adalah mengganti awal baris dengan teks itu:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        MIT.LICENSE | head -5
# -----8<----------------------------------------------------------------
# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the

4. Menghapus baris yang dipilih

Perintah substitusi di sed sangat serbaguna sehingga Anda dapat mengekspresikan sebagian besar transformasi teks dengan menggunakannya. Misalnya, untuk menghapus garis putus-putus di atas dan bawah teks lisensi, saya dapat menulis bahwa:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e 's/^.*----.*$//' \
        MIT.LICENSE | head -5

# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the

Substitusi yang kemudian telah diganti dengan string kosong semua teks:

Simbol Deskripsi
^ Mulai dari awal baris
.* Diikuti oleh urutan 0, 1 atau beberapa karakter
---- Diikuti oleh 4 tanda hubung
.* Diikuti oleh urutan 0, 1 atau beberapa karakter
$ Diikuti sampai akhir baris

Singkatnya, ini akan menggantikan seluruh baris dengan string kosong if itu berisi empat tanda hubung berturut-turut. Tapi baris kosong itu sendiri tetap ada di output dan akan muncul sebagai baris kosong.

Tergantung pada kebutuhan dan selera Anda, Anda mungkin juga ingin mempertimbangkan solusi alternatif di bawah ini. Saya membiarkan Anda memeriksanya secara rinci untuk menunjukkan dengan tepat perubahan dalam perintah dan mengidentifikasi sendiri apa konsekuensi dari hasilnya:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^.*----.*$//' \
        -e 's/^/# /' \
        MIT.LICENSE | head -5

Jika Anda menemukan ekspresi reguler yang digunakan untuk menghapus garis agak terlalu rumit, kami juga dapat memanfaatkan fitur sed lainnya. Hampir semua perintah dapat mengambil alamat opsional sebelum nama perintah. Jika ada, itu akan membatasi ruang lingkup perintah ke baris cocok alamat itu:

[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e '/----/s/^.*$//' \
        MIT.LICENSE | head -5

Sekarang perintah substitusi terbaru hanya akan diterapkan ke pencocokan baris (yaitu, "berisi") empat tanda hubung berturut-turut. Dan untuk setiap baris yang cocok, itu akan menggantikan semuanya (.* ) antara awal (^ ) dan akhir ($ ) dari baris dengan string kosong (// )

5. Menghapus baris yang dipilih

Di bagian sebelumnya, kami mengubah perintah substitusi untuk menghapus beberapa baris teks. Tapi garis kosong tetap ada. Terkadang ini diinginkan. Kadang-kadang tidak. Dalam kasus terakhir, Anda mungkin ingin menyelidiki hapus perintah untuk menghapus seluruh baris dari output:

# Below, the redirection '> LICENSE' is used to store
# the result of the sed command into the newly
# created LICENSE file:
[email protected]:~$ sed -e 's/<YEAR>/2018/'  \
        -e 's/<COPYRIGHT HOLDER>/Sylvain Leroux/' \
        -e 's/^/# /' \
        -e '/----/d' \
        MIT.LICENSE > LICENSE
[email protected]:~$ head -5 LICENSE
# Copyright 2018 Sylvain Leroux
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including

d adalah hapus nama perintah. Sama seperti s adalah pengganti nama perintah. Di sini, kami menentukan alamat sebelum perintah sehingga hanya baris yang cocok yang akan dihapus (tanpa alamat apa pun, d perintah akan menghapus setiap baris file)

6. Ubah ke huruf besar

Sampai sekarang, kami sebagian besar fokus pada bagian atas file lisensi. Tapi memang ada beberapa perubahan yang ingin saya lakukan sedikit lebih jauh ke dalam dokumen. Mari kita lihat dulu apa yang saya bicarakan:

[email protected]:~$ sed -ne '/The above/,$p' LICENSE
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# The software is provided "as is", without warranty of any kind,
# express or implied, including but not limited to the warranties of
# merchantability, fitness for a particular purpose and noninfringement.
# In no event shall the authors or copyright holders be liable for any
# claim, damages or other liability, whether in an action of contract,
# tort or otherwise, arising from, out of or in connection with the
# software or the use or other dealings in the software.

Pada perintah di atas, menggunakan opsi -n saya menonaktifkan pencetakan otomatis ruang pola. Itu berarti sed tidak akan lagi mencetak apa pun pada output kecuali saya secara eksplisit memintanya untuk melakukannya. Inilah yang saya lakukan dengan menggunakan perintah print (p). Perhatikan alih-alih menggunakan satu alamat sebelum perintah p, saya menggunakan rentang untuk menampilkan teks di antara baris yang berisi teks “Atas” dan akhir dokumen ($).

Perintah print dapat berguna ketika Anda perlu mengekstrak beberapa bagian dari sebuah file. Namun, untuk hari ini, saya hanya ingin menampilkan dua paragraf terakhir untuk menjelaskan apa yang saya butuhkan sekarang:karena ini adalah tradisi dengan file lisensi, saya ingin menutupi diri saya dengan memperjelas bahwa perangkat lunak disediakan "sebagaimana adanya". Jadi saya ingin menekankan paragraf terakhir (dimulai dengan "Perangkat lunak") dengan menulis ulang semua huruf besar.

Di bagian penggantian perintah substitusi, a &diganti dengan teks yang cocok dengan pola pencarian. Menggunakan ekstensi \U GNU, kita dapat mengubah huruf besar/kecil dari string pengganti:

[email protected]:~$ sed -i -e '/The software/,$s/.*/\U&/' LICENSE
[email protected]:~$ cat LICENSE

Dalam teks biasa s/.*/\U&/ berarti “ganti teks apa pun (.* ) dengan huruf besar (\U ) versinya sendiri (& ). Saya membiarkan Anda memverifikasi sendiri, paragraf terakhir sekarang harus ditulis dalam huruf besar semua. Omong-omong, Anda mungkin menyadarinya karena -i flag, perubahan diterapkan langsung ke file LICENSE.

Kita akan melihatnya secara lebih rinci di bagian selanjutnya. Sementara itu, saya membiarkan Anda berlatih dan memodifikasi perintah-perintah itu sesuai keinginan Anda. Setelah Anda memiliki file lisensi yang sesuai dengan selera Anda, sekarang saatnya untuk melihat cara memasukkannya sebelum setiap file sumber proyek.

7. Memasukkan file teks

Jika Anda mengharapkan beberapa perintah kompleks di sini, Anda akan kecewa:memasukkan file ke yang lain cukup mudah:

sed -i -e '1r LICENSE' script1.sh
cat script1.sh

Dua hal untuk dilihat di sini:

  1. r LICENSE ekspresi adalah perintah untuk membaca dan masukkan file eksternal ke dalam file yang sedang diproses. Di sini diawali dengan nomor 1 yang merupakan alamat yang hanya cocok dengan baris 1 dari file input.
  2. -i opsi memungkinkan mengubah file di tempat . Itu berarti sed akan membuat file sementara di belakang layar untuk menyimpan outputnya di sana, dan, setelah pemrosesan selesai, itu akan menggantikan file asli dengan yang dimodifikasi.

Efek samping yang menarik dari opsi '-i' adalah Anda dapat menentukan beberapa nama file pada baris perintah, dan sed akan menerapkan transformasi yang sama untuk masing-masing file secara independen :

sed -i -e '1r LICENSE' *.sh

8. Kembali ke masa depan

Sebagai contoh terakhir dari perintah sed, mari kita bayangkan beberapa tahun telah berlalu dan sekarang kita berada di tanggal 1 Januari 2024. Pemberitahuan hak cipta dari semua file harus diperbarui. Ada beberapa kasus penggunaan, tergantung kapan file proyek dibuat. Jadi, pemberitahuan Hak Cipta kami harus mengikuti salah satu dari dua format tersebut:

Hak cipta saat ini Deskripsi
Hak Cipta 2023 Untuk file yang dibuat tahun lalu
Hak Cipta 2018-2023 Untuk file yang dibuat sebelum tahun lalu

Kami dapat menangkap kedua kasus penggunaan tersebut sekaligus menggunakan ekspresi reguler yang diperluas (-E). Satu-satunya hal yang "diperpanjang" yang benar-benar akan kita gunakan di sini adalah tanda kurung:

sed -i -Ee 's/Copyright (....)(-....)?/Copyright \1-2024/' *.sh

Saya mendorong Anda untuk secara manual mengubah pemberitahuan hak cipta di file *.sh dan kemudian menjalankan perintah di atas dalam kasus penggunaan yang berbeda untuk melihat cara kerjanya.

Mungkin pada akhirnya membantu pemahaman Anda meskipun jika saya katakan, dalam pola pencarian:Hak Cipta::adalah teks literal yang akan cocok dengan kata demi kata; (… .)::mendefinisikan grup penangkap yang cocok dengan empat karakter arbitrer. Mudah-mudahan empat digit tahun; (-… .)?::mendefinisikan grup penangkap yang cocok dengan tanda hubung diikuti oleh empat karakter arbitrer. Tanda tanya di akhir menunjukkan bahwa grup adalah opsional. Ini mungkin, atau mungkin tidak, ada di baris input.

Dalam string pengganti:Hak Cipta::adalah teks literal yang akan disalin kata demi kata; \1::adalah konten dari grup penangkap pertama -2024::adalah teks literal yang akan disalin kata demi kata.

Jika Anda meluangkan waktu untuk memeriksa perintah sendiri, itu akan mengkonfirmasi jika saya menerapkan aturan tersebut ke kasus penggunaan yang dijelaskan dalam tabel sebelumnya, saya akan mendapatkan sesuatu seperti itu:

Teks yang cocok \1 \2 String pengganti
Hak Cipta 2023 2023 Hak Cipta 2023-2024
Hak Cipta 2018-2023 2018 -2023 Hak Cipta 2018-2024

Untuk mengakhiri panduan SED kami

Kami hanya menggores permukaan di sini. sed alat ini jauh lebih kuat dari itu. Namun, meskipun kita hanya melihat empat perintah (s , p , d , dan i ) dan beberapa konstruksi ekspresi reguler dasar (^ , $ , . , ? dan .* ), Anda sudah memiliki cukup pengetahuan untuk menyelesaikan banyak masalah sehari-hari.

Karena saya suka mengakhiri tutorial dengan sedikit tantangan, inilah yang saya usulkan kepada Anda:jika Anda telah mengunduh materi pendukung, Anda akan menemukan di direktori proyek sebuah file bernama hello.c . Ini adalah file sumber program C dasar:

[email protected]:~$ ls
hello.c  MIT.LICENSE  script1.sh  script2.sh
[email protected]:~$ gcc hello.c -o hello
[email protected]:~$ ./hello sylvain
Hello sylvain
[email protected]:~$ cat hello.c

Sudah ada beberapa komentar di file sumber. Dengan menggunakannya sebagai contoh sintaks komentar dalam bahasa pemrograman C, bisakah Anda memasukkan lisensi MIT ke hello.c file sumber menggunakan perintah sed? Anda dapat menggunakan satu atau beberapa perintah sed, Anda dapat menyalurkan output dari perintah sed ke perintah lain, Anda dapat menggunakan file-file sementara jika Anda mau, tetapi Anda tidak diizinkan untuk menggunakan perintah selain sed. Tentu saja, file sumber C masih harus dikompilasi setelah Anda memasukkan lisensi!

Saya membiarkan Anda sekarang memikirkan masalah kecil itu, dan saya harap Anda menikmati artikel itu dan video pendampingnya. Jika Anda ingin tahu lebih banyak tentang sed, beri tahu kami menggunakan bagian komentar!


Linux
  1. Memulai dengan ls

  2. Memulai PostgreSQL di Linux

  3. Memulai Dengan Multipass – Menjalankan VM Ubuntu

  1. Memulai dengan Zsh

  2. Memulai dengan perintah tac Linux

  3. Memulai dengan perintah cat Linux

  1. Memulai dengan GnuCash

  2. Memulai dengan Etcher.io

  3. Memulai dengan ekspresi reguler