Apa arti dari: a; $! N; dalam perintah sed?

11
$ (echo hello; echo there) | sed ':a;$!N;s/\n/string/;ta'
hellostringthere

sedPerintah di atas menggantikan karakter baris baru dengan string "string". Tapi saya tidak tahu arti dari :a;$!N;s/\n/string/;takutipan tunggal. Saya tahu bagian tengah s/\n/string/. Tapi saya tidak tahu fungsi bagian pertama ( :a;$!N;) dan terakhir ( ta).

Avinash Raj
sumber
2
silakan lihat stackoverflow.com/questions/1251999/… .
xiaodongjie
Bagaimana dengan bagian terakhir?
Avinash Raj
Perintah "t" cabang ke label bernama jika perintah pengganti terakhir memodifikasi ruang pola.
xiaodongjie

Jawaban:

17

Ini adalah, sedperintah yang diakui samar ,. Khusus (dari man sed):

: label
         Label untuk perintah b dan t.

t label
         Jika sebagai /// telah melakukan penggantian yang sukses sejak baris input terakhir dibaca dan sejak perintah t atau T terakhir, maka percabangan untuk melabeli; jika label dihilangkan, cabang ke akhir skrip.

n N Baca / tambahkan baris input berikutnya ke dalam ruang pola.

Jadi, skrip yang Anda poskan dapat dipecah menjadi (spasi ditambahkan untuk dibaca):

sed ':a;  $!N;  s/\n/string/;  ta'
     ---  ----  -------------  --
      |     |        |          |--> go back (`t`) to `a`
      |     |        |-------------> substitute newlines with `string`
      |     |----------------------> If this is not the last line (`$!`), append the 
      |                              next line to the pattern space.
      |----------------------------> Create the label `a`.

Pada dasarnya, apa yang dilakukan ini dapat ditulis dalam pseudocode sebagai

while (not end of line){
    append current line to this one and replace \n with 'string'
}

Anda dapat memahami ini sedikit lebih baik dengan contoh input yang lebih kompleks:

$ printf "line1\nline2\nline3\nline4\nline5\n" | sed ':a;$!N;s/\n/string/;ta'
line1stringline2stringline3stringline4stringline5

Saya tidak begitu yakin mengapa !$ini diperlukan. Sejauh yang saya tahu, Anda bisa mendapatkan hasil yang sama

printf "line1\nline2\nline3\nline4\nline5\n" | sed ':a;N;s/\n/string/;ta'
terdon
sumber
1
$ Untuk tidak cocok dengan baris baru terakhir, IMO.
Braiam
@Braiam tidak terlalu yakin tentang itu, $!bukan !$. Namun, mungkin juga !Ndan tidak $!.
terdon
Saya mencoba mengurai halaman texinfo tetapi tidak menemukan referensi untuk keduanya !Natau $!. Jadi, saya masih terus berpikir bahwa mencari apakah baris terakhir adalah baris baru atau EOF.
Braiam
4
Saya coba anggap $!sebagai 'rentang' alamat dengan operator komplemen postfix - jadi $!N(lakukan di Nmana - mana kecuali alamat $) benar-benar sintaks yang sama dengan sesuatu seperti m,n!d(hapus semuanya kecuali baris mke n).
steeldriver
:adalah analog dari gotolabel, dan sebenarnya :dulunya merupakan label goto dalam cangkang Thompson, jadi itu akan menjadi biasa bagi orang-orang di masa lalu yang menggunakan cangkang sed dan Thompson
Sergiy Kolodyazhnyy
0

Saya posting jawaban ini karena saya melihat banyak kebingungan tentang mengapa baris terakhir dikeluarkan ketika menjalankan N(melalui jalur menangani tali $!) dan karena OP bingung tentang makna :a;$!N; di sebuah perintah sed , tidak hanya di dalam satu spesifik ia diposting .

Nah, manfaat menggunakan $!Nbukannya Ntidak berlaku dalam contoh yang diusulkan (oleh OP dan oleh @terdon), karena tidak ada perintah "penting" (terus membaca) dilakukan pada baris terakhir setelah Nperintah. (Memang, hasilnya sama jika salah satu strip yang alamat baris off.)

Dalam contoh yang lebih kompleks (misalnya, mengganti this sentencedalam file, dengan dua kata yang kadang-kadang muncul pada satu baris dan beberapa kali lainnya pada dua baris), tidak termasuk baris terakhir untuk Nperintah bisa jadi sangat penting! Jika baris terakhir tidak dikecualikan, setelah dieksekusi Ndi atasnya, sedhits EOFdan segera keluar, mencegah semua perintah berikutnya (percabangan juga, yaitu tdan b) dieksekusi.

Dalam contoh yang terlalu sederhana yang ditunjukkan, kita dapat dengan aman menghapus $!dan membiarkan sedkegagalan dalam mengeksekusi Ndan kembali karena sperintah yang dibatalkan tidak akan melakukan apa pun jika dieksekusi, karena tidak ada yang \ncocok.

Enrico Maria De Angelis
sumber