GNU/Linux >> Belajar Linux >  >> Linux

Konsep 'Hold space' dan 'Pattern space' di sed

@Ed Morton:Saya tidak setuju dengan Anda di sini. Saya menemukan sed sangat berguna dan sederhana (setelah Anda mengetahui konsep pola dan menahan buffer) untuk menghasilkan cara yang elegan untuk melakukan multiline grepping.

Misalnya, mari ambil file teks yang memiliki nama host dan beberapa informasi tentang setiap host, dengan banyak sampah di antaranya yang tidak saya pedulikan.

Host: foo1
some junk, doesnt matter
some junk, doesnt matter
Info: about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Info: a second line about foo1 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter
Host: foo2
some junk, doesnt matter
Info: about foo2 that I really care about!!
some junk, doesnt matter
some junk, doesnt matter

Bagi saya, skrip awk hanya untuk mendapatkan baris dengan nama host dan info yang sesuai baris akan mengambil sedikit lebih dari apa yang dapat saya lakukan dengan sed:

sed -n '/Host:/{h}; /Info/{x;p;x;p;}' myfile.txt

keluaran terlihat seperti:

Host: foo1
Info: about foo1 that I really care about!!
Host: foo1
Info: a second line about foo1 that I really care about!!
Host: foo2
Info: about foo2 that I really care about!!

(Perhatikan bahwa Host: foo1 muncul dua kali di keluaran.)

Penjelasan:

  1. -n menonaktifkan keluaran kecuali dicetak secara eksplisit
  2. kecocokan pertama, temukan dan letakkan Host: baris ke buffer penahan (h)
  3. kecocokan kedua, menemukan baris Info:berikutnya, tetapi pertama menukar (x) baris saat ini dalam buffer pola dengan buffer penahan, dan mencetak (p) Host: baris, lalu tukar kembali (x) dan cetak (p) baris Info:.

Ya, ini adalah contoh sederhana, tapi saya menduga ini adalah masalah umum yang dengan cepat ditangani oleh sed one-liner sederhana. Untuk tugas yang jauh lebih kompleks, seperti tugas yang tidak dapat Anda andalkan pada urutan tertentu yang dapat diprediksi, awk mungkin lebih cocok.


Saat sed membaca file baris demi baris, baris yang sedang dibaca dimasukkan ke dalam pola buffer (ruang pola). Buffer pola seperti buffer sementara, alas awal tempat informasi saat ini disimpan. Saat Anda memberi tahu sed untuk mencetak, itu mencetak buffer pola.

Hold buffer / hold space seperti penyimpanan jangka panjang, sehingga Anda dapat menangkap sesuatu, menyimpannya, dan menggunakannya kembali nanti saat sed sedang memproses baris lain. Anda tidak langsung memproses ruang tunggu, sebaliknya, Anda perlu menyalinnya atau menambahkannya ke ruang pola jika Anda ingin melakukan sesuatu dengannya. Misalnya, perintah cetak p mencetak ruang pola saja. Begitu juga dengan s beroperasi pada ruang pola.

Ini contohnya:

sed -n '1!G;h;$p'

(opsi -n menekan pencetakan garis otomatis)

Ada tiga perintah di sini:1!G , h dan $p . 1!G memiliki alamat, 1 (baris pertama), tetapi ! berarti bahwa perintah akan dijalankan di mana saja tetapi pada baris pertama. $p di sisi lain hanya akan dieksekusi pada baris terakhir. Jadi yang terjadi adalah ini:

  1. baris pertama dibaca dan disisipkan secara otomatis ke dalam ruang pola
  2. pada baris pertama, perintah pertama tidak dijalankan; h salin baris pertama ke dalam tahan ruang.
  3. sekarang baris kedua menggantikan apapun yang ada di ruang pola
  4. pada baris kedua, pertama kita eksekusi G , menambahkan konten buffer penahan ke buffer pola, memisahkannya dengan baris baru. Ruang pola sekarang berisi baris kedua, baris baru, dan baris pertama.
  5. Lalu, h perintah menyisipkan konten gabungan dari buffer pola ke dalam ruang tunggu, yang sekarang menyimpan baris terbalik dua dan satu.
  6. Kita lanjutkan ke baris nomor tiga -- lanjutkan ke poin (3) di atas.

Akhirnya, setelah baris terakhir dibaca dan ruang tunggu (berisi semua baris sebelumnya dalam urutan terbalik) telah ditambahkan ke ruang pola, ruang pola dicetak dengan p . Seperti yang sudah Anda duga, di atas melakukan persis seperti tac perintah tidak -- mencetak file secara terbalik.


Meskipun jawaban @Januari dan contohnya bagus, penjelasannya tidak cukup untuk saya. Saya harus mencari dan belajar banyak sampai saya berhasil memahami bagaimana tepatnya sed -n '1!G;h;$p' bekerja. Jadi saya ingin menguraikan perintah untuk orang seperti saya.

Pertama-tama, mari kita lihat apa yang dilakukan perintah tersebut.

$ echo {a..d} | tr ' ' '\n' # Prints from 'a' to 'd' in each line
a
b
c
d
$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;$p'
d
c
b
a

Ini membalik input seperti tac perintah tidak.

sed membaca baris demi baris, jadi mari kita lihat apa yang terjadi di ruang pola dan ruang penyimpanan di setiap baris. Sebagai h perintah menyalin konten ruang pola ke ruang tunggu, kedua ruang memiliki teks yang sama.

Read line    Pattern Space / Hold Space    Command executed
-----------------------------------------------------------
a            a$                            h
b            b\na$                         1!G;h
c            c\nb\na$                      1!G;h
d            d\nc\nb\na$                   1!G;h;$p

Di baris terakhir, $p mencetak d\nc\nb\na$ yang diformat menjadi

d
c
b
a

Jika Anda ingin melihat ruang pola untuk setiap baris, Anda dapat menambahkan l perintah.

$ echo {a..d} | tr ' ' '\n' | sed -n '1!G;h;l;$p'
a$
b\na$
c\nb\na$
d\nc\nb\na$
d
c
b
a

Saya merasa sangat terbantu dengan menonton video tutorial ini Memahami cara kerja sed, karena pria tersebut menunjukkan bagaimana setiap ruang akan digunakan selangkah demi selangkah. Spasi penangguhan dirujuk dalam tutorial ke-4, tetapi saya sarankan menonton semua video jika Anda tidak terbiasa dengan sed .

Juga dokumen sed GNU dan tutorial Sed Bruce Barnett adalah referensi yang sangat bagus.


Linux
  1. Belajar menggunakan editor teks Sed

  2. Perintah Sed Linux:Penggunaan dan Contoh

  3. Memanipulasi teks pada baris perintah dengan sed

  1. Memanipulasi X Key Dan Pointer Grabs Di Command Line?

  2. Bagaimana Cara Menyisipkan Teks Sebelum Baris Pertama Sebuah File?

  3. Cetak Garis Pencocokan Dan Garis Ke-N Dari Garis Yang Cocok?

  1. Cetak Baris Sebelumnya Setelah Pencocokan Pola Menggunakan Sed?

  2. Temukan Nomor Baris Yang Berisi Pola Menggunakan Pembatas Regex Khusus?

  3. Bagaimana Cara Mengubah Panjang Baris Default Untuk Od Dan Hexdump?