Cara Menggunakan Perintah sed di Linux

Mungkin terdengar gila, tetapi sedperintah Linux adalah penyunting teks tanpa antara muka. Anda boleh menggunakannya dari baris perintah untuk memanipulasi teks dalam fail dan aliran. Kami akan menunjukkan kepada anda bagaimana memanfaatkan kekuatannya.

Kekuatan sed

The sedarahan adalah sedikit seperti catur: ia mengambil masa satu jam untuk belajar asas-asas dan seumur hidup untuk menguasai mereka (atau, sekurang-kurangnya banyak amalan). Kami akan menunjukkan pilihan pertunjukan pembukaan di setiap kategori sedfungsi utama.

sedadalah penyunting aliran yang berfungsi pada input paip atau fail teks. Namun, ia tidak mempunyai antara muka penyunting teks interaktif. Sebaliknya, anda memberikan arahan untuk mengikutinya kerana ia berfungsi melalui teks. Ini semua berfungsi di Bash dan shell baris perintah yang lain.

Dengan sedanda boleh melakukan semua perkara berikut:

  • Pilih teks
  • Teks pengganti
  • Tambahkan baris ke teks
  • Padamkan baris dari teks
  • Ubah (atau simpan) fail asal

Kami telah menyusun contoh-contoh kami untuk memperkenalkan dan menunjukkan konsep, bukan untuk menghasilkan perintah yang paling pendek (dan paling tidak dapat didekati) sed. Walau bagaimanapun, fungsi pemadanan corak dan pemilihan teks sed sangat bergantung pada ungkapan biasa (regex). Anda akan memerlukan beberapa keakraban dengan ini untuk mendapatkan yang terbaik sed.

BERKAITAN: Cara Menggunakan Ekspresi Biasa (regex) di Linux

Contoh Mudah

Pertama, kita akan gunakan echountuk menghantar beberapa teks sedmelalui paip, dan sed mengganti sebahagian teks. Untuk melakukannya, kami taipkan perkara berikut:

echo howtogonk | sed 's / gonk / geek /'

The echoarahan menghantar "howtogonk" ke dalam sed, dan peraturan penggantian mudah kami ( "s" bermaksud penggantian) digunakan. sed mencari teks input untuk terjadinya rentetan pertama, dan akan menggantikan sebarang padanan dengan yang kedua.

Rentetan "gonk" diganti dengan "geek", dan rentetan baru dicetak di tetingkap terminal.

Penggantian mungkin merupakan penggunaan yang paling biasa sed. Sebelum kita dapat menyelami pengganti dengan lebih mendalam, kita perlu tahu bagaimana memilih dan memadankan teks.

Memilih Teks

Kami akan memerlukan fail teks untuk contoh kami. Kami akan menggunakan satu yang berisi pilihan ayat dari puisi epik Samuel Taylor Coleridge "The Rime of the Ancient Mariner."

Kami menaip perkara berikut untuk melihatnya dengan less:

kurang coleridge.txt

Untuk memilih beberapa baris dari fail, kami menyediakan garis permulaan dan akhir julat yang ingin kami pilih. Nombor tunggal memilih satu baris.

Untuk mengekstrak baris satu hingga empat, kami taipkan arahan ini:

sed -n '1,4p' coleridge.txt

Perhatikan tanda koma antara 1dan 4. Yang pbermaksud "mencetak garis dipadankan." Secara lalai,  sed mencetak semua baris. Kami akan melihat semua teks dalam fail dengan garis yang sesuai dicetak dua kali. Untuk mengelakkannya, kami akan menggunakan pilihan -n(senyap) untuk menekan teks yang tidak sepadan.

Kami menukar nombor garis sehingga kami dapat memilih ayat yang berbeza, seperti yang ditunjukkan di bawah:

sed -n '6,9p' coleridge.txt

Kita boleh menggunakan pilihan -e(ekspresi) untuk membuat beberapa pilihan. Dengan dua ungkapan, kita dapat memilih dua ayat, seperti:

sed -n -e '1,4p' -e '31, 34p 'coleridge.txt

Sekiranya kita mengurangkan nombor pertama dalam ungkapan kedua, kita dapat memasukkan kosong di antara dua ayat tersebut. Kami menaip perkara berikut:

sed -n -e '1,4p' -e '30, 34p 'coleridge.txt

Kami juga dapat memilih baris permulaan dan memberitahu sed untuk melangkah ke fail dan mencetak baris gantian, setiap baris kelima, atau melangkau sebilangan baris. Perintahnya serupa dengan yang kami gunakan di atas untuk memilih julat. Akan tetapi, kali ini kita akan menggunakan tilde ( ~) dan bukan koma untuk memisahkan angka.

Nombor pertama menunjukkan garis permulaan. Nombor kedua memberitahu sedbaris mana selepas garis permulaan yang ingin kita lihat. Nombor 2 bermaksud setiap baris kedua, 3 bermaksud setiap baris ketiga, dan seterusnya.

Kami menaip perkara berikut:

sed -n '1 ~ 2p' coleridge.txt

Anda tidak akan selalu mengetahui di mana teks yang anda cari berada di dalam fail, yang bermaksud nombor baris tidak akan banyak membantu. Namun, anda juga dapat menggunakan sed untuk memilih baris yang berisi pola teks yang sepadan. Sebagai contoh, mari kita ekstrak semua baris yang bermula dengan "Dan".

Caret ( ^) mewakili permulaan garis. Kami akan memasukkan istilah carian kami dalam garis miring ke depan ( /). Kami juga menyertakan spasi setelah "Dan" sehingga kata-kata seperti "Android" tidak akan disertakan dalam hasilnya.

Membaca sedskrip pada awalnya agak sukar. Yang /p bermaksud "cetak," hanya seperti yang berlaku dalam perintah-perintah kami yang digunakan di atas. Namun, dalam perintah berikut, garis miring ke depan mendahului:

sed -n '/ ^ Dan / p' coleridge.txt

Tiga baris yang dimulakan dengan "Dan" diekstrak dari fail dan dipaparkan untuk kita.

Membuat Penggantian

Dalam contoh pertama kami, kami menunjukkan format asas sedpengganti berikut:

echo howtogonk | sed 's / gonk / geek /'

Yang smemberitahu sed ini adalah penggantian. Rentetan pertama adalah corak carian, dan yang kedua adalah teks yang dengannya kami mahu mengganti teks yang sesuai. Sudah tentu, seperti semua perkara Linux, syaitan ada dalam perinciannya.

Kami menaip yang berikut untuk mengubah semua kejadian "hari" menjadi "minggu", dan memberi lebih banyak masa kepada pelaut dan albatros untuk mengikat:

sed -n / s / hari / minggu / p 'coleridge.txt

Pada baris pertama, hanya kejadian kedua "hari" yang diubah. Ini kerana sedberhenti selepas perlawanan pertama setiap baris. Kita harus menambahkan "g" di akhir ungkapan, seperti yang ditunjukkan di bawah, untuk melakukan carian global sehingga semua pertandingan di setiap baris diproses:

sed -n / s / hari / minggu / gp 'coleridge.txt

Ini sesuai dengan tiga daripada empat di barisan pertama. Kerana kata pertama adalah "Hari", dan sedpeka huruf besar kecil, kata ini tidak menganggap kejadian itu sama dengan "hari".

Kami menaip yang berikut, menambahkan i perintah pada akhir ungkapan untuk menunjukkan ketidakpekaan huruf besar-kecil:

sed -n 's / hari / minggu / gip' coleridge.txt

Ini berfungsi, tetapi anda mungkin tidak selalu mahu menghidupkan kepekaan huruf besar-besaran untuk semuanya. Dalam keadaan seperti itu, anda boleh menggunakan kumpulan regex untuk menambahkan ketidakpekaan kes khusus corak.

Sebagai contoh, jika kita memasukkan watak dalam tanda kurung persegi ( []), mereka ditafsirkan sebagai "watak apa pun dari senarai watak ini."

Kami menaip yang berikut, dan memasukkan "D" dan "d" dalam kumpulan, untuk memastikannya sesuai dengan "Hari" dan "hari":

sed -n / s / [dd] ay / minggu / gp 'coleridge.txt

Kami juga boleh menyekat penggantian pada bahagian fail. Katakan fail kami mengandungi jarak yang pelik pada ayat pertama. Kita boleh menggunakan perintah biasa berikut untuk melihat ayat pertama:

sed -n '1,4p' coleridge.txt

Kami akan mencari dua ruang dan menggantinya dengan satu. Kami akan melakukan ini secara global sehingga tindakan diulang secara keseluruhan. Untuk jelas, corak carian adalah ruang, asterisk ruang ( *), dan rentetan penggantian adalah ruang tunggal. Yang 1,4menyekat penggantian kepada empat baris pertama fail.

Kami mengumpulkan semua itu dalam arahan berikut:

sed -n '1,4 s / * / / gp' coleridge.txt

Ini berfungsi dengan baik! Corak carian adalah yang penting di sini. Tanda bintang ( *) mewakili sifar atau lebih daripada watak sebelumnya, yang merupakan spasi. Oleh itu, corak carian mencari rentetan satu ruang atau lebih.

Sekiranya kita menggantikan satu ruang untuk urutan pelbagai ruang, kita akan mengembalikan fail ke jarak biasa, dengan satu ruang di antara setiap perkataan. Ini juga akan menggantikan satu ruang untuk satu ruang dalam beberapa kes, tetapi ini tidak akan mempengaruhi apa-apa yang buruk - kita masih akan mendapat hasil yang diinginkan.

Sekiranya kita memasukkan perkara berikut dan mengurangkan corak carian menjadi satu ruang, anda akan melihat dengan segera mengapa kita mesti memasukkan dua ruang:

sed -n '1,4 s / * / / gp' coleridge.txt

Kerana tanda bintang sepadan dengan sifar atau lebih daripada watak sebelumnya, ia melihat setiap watak yang bukan ruang sebagai "ruang sifar" dan menerapkan penggantian untuknya.

Walau bagaimanapun, jika kita memasukkan dua ruang dalam corak carian,  sedmesti mencari sekurang-kurangnya satu watak ruang sebelum menerapkan penggantian. Ini memastikan watak-watak nonspace tidak akan tersentuh

Kami menaip yang berikut, menggunakan -e(ungkapan) yang kami gunakan sebelumnya, yang membolehkan kami membuat dua atau lebih penggantian secara serentak:

sed -n -e / s / motion / flutter / gip '-e' s / ocean / gutter / gip 'coleridge.txt

Kita boleh mencapai hasil yang sama jika kita menggunakan titik koma ( ;) untuk memisahkan dua ungkapan, seperti:

sed -n 's / motion / flutter / gip; s / ocean / gutter / gip' coleridge.txt

Ketika kami menukar "hari" untuk "minggu" dalam perintah berikut, contoh "hari" dalam ungkapan "baik sehari" juga ditukar:

sed -n / s / [dd] ay / minggu / gp 'coleridge.txt

Untuk mengelakkan ini, kita hanya boleh mencuba penggantian pada garis yang sesuai dengan corak lain. Sekiranya kita mengubah perintah untuk mempunyai corak carian pada permulaannya, kita hanya akan mempertimbangkan untuk beroperasi pada garis yang sesuai dengan corak itu.

Kami menaip yang berikut untuk menjadikan corak pencocokan kami dengan kata "setelah":

sed -n '/ after / s / [Dd] ay / week / gp' coleridge.txt

Itu memberi kita respons yang kita mahukan.

Penggantian Lebih Kompleks

Mari beri rehat dan gunakan Coleridge seduntuk mengekstrak nama dari etc/passwdfail.

Terdapat cara yang lebih pendek untuk melakukan ini (lebih lanjut kemudian), tetapi kita akan menggunakan cara yang lebih panjang di sini untuk menunjukkan konsep lain. Setiap item yang sesuai dalam corak pencarian (disebut subekspresi) dapat bernomor (hingga maksimum sembilan item). Anda kemudian boleh menggunakan nombor ini dalam sedperintah anda  untuk merujuk subekspresi tertentu.

Anda mesti memasukkan subekspresi dalam kurungan [ ()] agar ini berfungsi. Tanda kurung juga mesti didahului dengan garis miring ke belakang ( \) untuk mengelakkannya diperlakukan sebagai watak normal.

Untuk melakukan ini, anda akan menaip perkara berikut:

sed 's / \ ([^:] * \). * / \ 1 /' / etc / passwd

Mari pecahkan ini:

  • sed 's/: The sedarahan dan permulaan ungkapan penggantian.
  • \(: Tanda kurung pembuka [ (] merangkumi subekspresi, didahului dengan garis miring terbalik ( \).
  • [^:]*: Subekspresi pertama istilah carian mengandungi kumpulan dalam tanda kurung persegi. Caret ( ^) bermaksud "tidak" apabila digunakan dalam kumpulan. Kumpulan bermaksud setiap watak yang bukan titik dua ( :) akan diterima sebagai padanan.
  • \): Tanda kurung penutup [ )] dengan garis miring terbalik ( \).
  • .*: Subekspresi carian kedua ini bermaksud "watak apa pun dan sebilangannya."
  • /\1: Bahagian penggantian ungkapan mengandungi 1didahului dengan garis miring terbalik ( \). Ini mewakili teks yang sepadan dengan subekspresi pertama.
  • /': Slash ke depan penutup ( /) dan petikan tunggal ( ') menamatkan sedperintah.

Apa maksudnya ini adalah kita akan mencari rentetan watak yang tidak mengandungi titik dua ( :), yang akan menjadi contoh pertama teks yang sepadan. Kemudian, kami mencari perkara lain di baris itu, yang akan menjadi contoh kedua teks yang sepadan. Kami akan mengganti keseluruhan baris dengan teks yang sepadan dengan subekspresi pertama.

Setiap baris dalam /etc/passwdfail bermula dengan nama pengguna yang diakhiri dengan titik dua. Kami memadankan semuanya hingga titik dua pertama, dan kemudian menggantikan nilai itu dengan keseluruhan garis. Oleh itu, kami telah mengasingkan nama pengguna.

Seterusnya, kami akan memasukkan subekspresi kedua dalam tanda kurung [ ()] sehingga kami juga dapat merujuknya dengan nombor. Kami juga akan menggantikan \1 dengan \2. Perintah kami sekarang akan mengganti keseluruhan baris dengan segala-galanya dari titik dua ( :) hingga akhir baris.

Kami menaip perkara berikut:

sed 's / \ ([^:] * \) \ (. * \) / \ 2 /' / etc / passwd

Perubahan kecil itu membalikkan makna perintah, dan kami mendapat segalanya kecuali nama pengguna.

Sekarang, mari kita lihat cara cepat dan mudah untuk melakukan ini.

Istilah carian kami adalah dari titik dua pertama ( :) hingga akhir baris. Kerana ungkapan penggantian kami kosong ( //), kami tidak akan mengganti teks yang dipadankan dengan apa-apa.

Oleh itu, kami taipkan perkara berikut, memotong segala-galanya dari titik dua pertama ( :) hingga akhir baris, hanya tinggal nama pengguna:

sed 's /:.*// "/ etc / passwd

Mari kita lihat contoh di mana kita merujuk perlawanan pertama dan kedua dalam arahan yang sama.

Kami mempunyai fail koma ( ,) yang memisahkan nama depan dan belakang. Kami ingin menyenaraikannya sebagai "nama belakang, nama depan." Kita dapat menggunakan  cat, seperti gambar di bawah, untuk melihat apa yang ada di dalam file:

kucing geeks.txt

Seperti banyak sedperintah, yang berikutnya mungkin kelihatan tidak dapat ditembus pada mulanya:

sed 's / ^ \ (. * \), \ (. * \) $ / \ 2, \ 1 / g' geeks.txt

Ini adalah arahan penggantian seperti yang lain yang telah kami gunakan, dan corak cariannya agak mudah. Kami akan memecahkannya di bawah:

  • sed 's/: Perintah penggantian biasa.
  • ^: Kerana karet tidak berada dalam kumpulan ( []), itu bermaksud "Permulaan baris."
  • \(.*\),: Subekspresi pertama adalah sebilangan besar aksara. Ini dibungkus dalam tanda kurung [ ()], yang masing-masing didahului dengan garis miring terbalik ( \) sehingga kita dapat merujuknya dengan angka. Seluruh corak carian kami setakat ini diterjemahkan sebagai carian dari awal baris hingga koma pertama ( ,) untuk sebilangan besar watak mana pun.
  • \(.*\):  Subekspresi seterusnya adalah (sekali lagi) sebilangan watak apa pun. Ini juga disertakan dalam tanda kurung [ ()], yang keduanya didahului dengan garis miring terbalik ( \) sehingga kita dapat merujuk teks yang sesuai dengan angka.
  • $/: Tanda dolar ( $) mewakili akhir garis dan akan membolehkan carian kami berterusan hingga akhir baris. Kami menggunakan ini hanya untuk memperkenalkan tanda dolar. Kami tidak benar-benar memerlukannya di sini, kerana tanda bintang ( *) akan sampai ke hujung baris dalam senario ini. Garis depan ( /) melengkapkan bahagian corak carian.
  • \2,\1 /g': Kerana kami memasukkan dua subekspresi kami dalam kurungan, kami dapat merujuk kedua-duanya dengan nombor mereka. Oleh kerana kami mahu membalikkan susunan, kami taipkannya sebagai second-match,first-match. Nombor mesti didahului dengan garis miring terbalik ( \).
  • /g: Ini membolehkan perintah kita berfungsi secara global di setiap baris.
  • geeks.txt: Fail yang sedang kami jalankan.

Anda juga boleh menggunakan perintah Potong ( c) untuk menggantikan keseluruhan baris yang sesuai dengan corak carian anda. Kami menaip yang berikut untuk mencari baris dengan kata "leher" di dalamnya, dan menggantinya dengan rentetan teks baru:

sed '/ leher / c Di sekitar pergelangan tangan saya digantung' coleridge.txt

Baris baru kami kini muncul di bahagian bawah ekstrak kami.

Memasukkan Garis dan Teks

Kami juga boleh memasukkan baris dan teks baru ke dalam fail kami. Untuk memasukkan baris baru setelah ada yang sesuai, kami akan menggunakan perintah Lampirkan ( a)

Inilah fail yang akan kami bekerjasama:

kucing geeks.txt

Kami telah memberi nombor untuk menjadikannya lebih mudah diikuti.

Kami menaip yang berikut untuk mencari baris yang mengandungi perkataan "Dia", dan memasukkan baris baru di bawahnya:

sed '/ He / a -> Dimasukkan!' geeks.txt

Kami menaip yang berikut dan memasukkan Command Insert ( i) untuk memasukkan baris baru di atas yang mengandungi teks yang sepadan:

sed '/ He / i -> Dimasukkan!' geeks.txt

Kita dapat menggunakan ampersand ( &), yang mewakili teks asli yang sesuai, untuk menambahkan teks baru ke garis yang sesuai. \1 ,  \2, Dan sebagainya, mewakili subexpressions sepadan.

Untuk menambahkan teks ke permulaan baris, kami akan menggunakan perintah penggantian yang sesuai dengan semua yang ada di baris, digabungkan dengan klausa penggantian yang menggabungkan teks baru kami dengan baris asal.

Untuk melakukan semua ini, kami taipkan perkara berikut:

sed 's /.*/--> Disisipkan & /' geeks.txt

Kami menaip yang berikut, termasuk Gperintah, yang akan menambahkan baris kosong di antara setiap baris:

sed 'G' geeks.txt

Jika anda ingin menambah dua atau lebih baris kosong, anda boleh menggunakan G;GG;G;Gdan sebagainya.

Memadamkan Garis

Perintah Hapus ( d) menghapus baris yang sesuai dengan corak carian, atau yang ditentukan dengan nombor atau julat garis.

Sebagai contoh, untuk menghapus baris ketiga, kami akan menaip perkara berikut:

sed '3d' geeks.txt

Untuk menghapus julat baris empat hingga lima, kami taipkan yang berikut:

sed '4,5d' geeks.txt

Untuk menghapus garis di luar jarak, kami menggunakan tanda seru ( !), seperti yang ditunjukkan di bawah:

sed '6,7! d' geeks.txt

Menyimpan Perubahan Anda

Sejauh ini, semua hasil kami telah dicetak ke tetingkap terminal, tetapi kami belum menyimpannya di mana sahaja. Untuk menjadikannya tetap, anda boleh menulis perubahan anda ke fail asal atau mengalihkannya ke fail baru.

Menimpa fail asal anda memerlukan berhati-hati. Sekiranya sedarahan anda salah, anda mungkin membuat beberapa perubahan pada fail asal yang sukar dibatalkan.

Untuk ketenangan hati, sed boleh membuat sandaran fail asal sebelum melaksanakan perintahnya.

Anda boleh menggunakan pilihan Di tempat ( -i) untuk memberitahu  seduntuk menulis perubahan pada fail asal, tetapi jika anda menambahkan pelanjutan fail ke file tersebut, sed akan membuat sandaran fail asal ke yang baru. Ia akan mempunyai nama yang sama dengan fail asal, tetapi dengan sambungan fail baru.

Untuk menunjukkan, kami akan mencari mana-mana baris yang mengandungi perkataan "Dia" dan menghapusnya. Kami juga akan menyandarkan fail asal kami ke fail baru menggunakan pelanjutan BAK.

Untuk melakukan semua ini, kami taipkan perkara berikut:

sed -i'.bak '' /^.*He.*$/d 'geeks.txt

Kami menaip perkara berikut untuk memastikan fail sandaran kami tidak berubah:

kucing geeks.txt.bak

Kami juga boleh mengetik berikut untuk mengalihkan output ke fail baru dan mencapai hasil yang serupa:

sed -i'.bak '' /^.*He.*$/d 'geeks.txt> new_geeks.txt

Kami gunakan catuntuk mengesahkan perubahan ditulis ke file baru, seperti yang ditunjukkan di bawah ini:

kucing baru_geeks.txt

Mempunyai semua itu

Seperti yang anda mungkin perhatikan, walaupun buku asas cepat sedini cukup panjang. Terdapat banyak perintah ini, dan ada banyak lagi yang boleh anda lakukan dengannya.

Walau bagaimanapun, semoga konsep asas ini memberikan asas yang kukuh di mana anda dapat membangun semasa anda terus mempelajari lebih lanjut.