Pertanyaan saya terkait dengan sed
solusi-spesifik yang diberikan dalam jawaban ini untuk pertanyaan ini dari reverse grepping . The sed
/ grep
solusi yang saya tidak dapat menguraikan adalah sebagai berikut satu:
sed '1!G;h;$!d' file
Dapatkah seseorang tolong menguraikan perintah ini?
Saya tahu dari pengetahuan VI (M) bahwa G menunjukkan baris terakhir dari file dan bahwa pada sed bang (!) Diikuti oleh alamat bekerja sedikit seperti grep -v
itu adalah untuk mengatakan bahwa itu tidak akan cocok dengan baris itu. Tapi secara keseluruhan skrip inline di atas berada di luar saya.
sed
resep rumit ini adalah cara yang sangat tidak efisien (O (n ^ 2/2) kompleksitas) untuk membalikkan baris dalam file. Akan sangat lambat untuk file dengan banyak baris. Untuk alternatif pembalikan urutan-urutan yang jauh lebih efisien lihattac
dari GNU coreutils.Jawaban:
Ini membalikkan file baris demi baris.
Pertama,
sed
memiliki ruang tahan dan ruang pola . Kita harus membedakan antara mereka sebelum berkonsentrasi pada perintah khusus itu.Ketika
sed
membaca baris baru, itu dimuat ke dalam ruang pola. Oleh karena itu, ruang itu ditimpa setiap kali baris baru diproses. Di sisi lain, ruang penahanan konsisten untuk seluruh pemrosesan dan nilai-nilai dapat disimpan di sana untuk penggunaan selanjutnya.Untuk perintah:
Ada 3 perintah dalam pernyataan ini:
1!G
,h
dan$!d
1!G
berarti bahwaG
perintah dijalankan pada setiap baris kecuali yang pertama (yang!
meniadakan1
).G
berarti menambahkan apa yang ada di ruang pegang ke dalam ruang pola.h
berlaku untuk setiap baris. Ini menyalin ruang pola ke ruang pegang (dan menimpanya).$!d
berlaku untuk setiap baris kecuali yang terakhir ($
mewakili baris terakhir,!
meniadakannya).d
adalah perintah untuk menghapus garis (pola spasi).sed
jalankanh
perintah. Baris pertama disalin ke ruang tunggu. Kemudian dihapus, karena cocok dengan$!
kondisi.sed
melanjutkan dengan baris kedua.1!
(itu bukan baris pertama), dan jadi ruang penahanan (yang memiliki baris pertama) ditambahkan ke ruang pola (yang memiliki baris kedua). Setelah itu, dalam ruang pola, sekarang ada baris kedua diikuti oleh baris pertama, dibatasi oleh baris baru. Sekarang,h
perintah berlaku (seperti di setiap baris); semua yang ada dalam pola ruang disalin ke ruang tunggu. Pernyataan ketiga ($!d
) berlaku: Baris dihapus dari ruang pola.$
) hampir semua Langkah 2 dilakukan, tetapi bukan bagian hapus (d
).sed
, ketika dipanggil tanpa-n
, mencetak ruang pola secara otomatis di akhir pemrosesan untuk setiap jalur input. Jadi, ketika tidak dihapus, ruang pola dicetak. Ini sekarang berisi semua baris dalam urutan terbalik .sumber
h
perintah menyalin ruang pola ke ruang tunggu, yang bertahan sampaised
berakhir. Setelah akhir skrip semuanya dibersihkan, karena biner keluar.sed
hanya ada satu ruang tunggu. Ini seperti variabel yang dapat berisi sesuatu.-n
kita harus menghapus setiap baris kecuali yang terakhir. Pada baris terakhir sed menambahkan semua dari ruang pegang ke ruang pola. Dan karenad
perintah tidak akan dieksekusi, baris dicetak (baris ini sekarang berisi seluruh file terbalik).h
perintah pada baris terakhir adalah semacam no-op." (Dengan penekanan tambahan, dan sedikit diparafrasekan). Dia benar; ketikased
memproses baris terakhir input ,G
membaca ruang penahanan (untuk menambahkannya ke ruang pola), dan kemudianh
menyalin ruang pola ke ruang penahanan, yang tidak pernah direferensikan lagi . Kita bisa saja mengatakansed 'G;$!h;$!d'
ataused 'G;$!{h;d}'
. (2) Kita bisa menghindari menggunakand
dengan mengatakansed -n 'G;h;$p'
.