Dokumentasi sed POSIX mengatakan:
Suatu fungsi dapat didahului oleh satu atau lebih '!' karakter, dalam hal ini fungsi akan diterapkan jika alamat tidak memilih ruang pola. Nol atau lebih karakter <blank> harus diterima sebelum '!' Yang pertama karakter. Tidak ditentukan apakah karakter <blank> dapat mengikuti '!' karakter, dan aplikasi yang sesuai tidak boleh mengikuti '!' karakter dengan karakter <blank>.
Jadi, dengan sed POSIX, kita dapat:
sed -e '/pattern/!d' file
Itu sama dengan menulis:
sed -e '/pattern/!!d' file
Dan !!!d
dan n
dari seru tanda masih baik-baik saja (Diuji dengan tiga sed
versi dari pusaka toolchest ). Saya tidak melihat adanya manfaat di antara banyak, bukan satu tanda seru.
Mengapa spec mengijinkan sintaks itu dan bagaimana itu berguna dalam aplikasi dunia nyata?
Tampaknya GNU sed tidak sesuai dalam kasus ini, itu akan mengeluh jika kita menggunakan beberapa tanda seru:
$ sed -e '/pattern/!!d' file
sed: -e expression #1, char 11: multiple `!'s
!
bertindak sebagai toggle,/pattern/!!
sama dengan/pattern/
, dan/pattern/!!!
sama dengan/pattern/!
. Pada beberapa FreeBSD!
sama dengan satu.sed
skrip dapat dibuat . Diberikan POSIXsed
, seharusnya menjadi hal yang sangat sederhana untuk menulis naskah penulisansed
. Jadi jika Anda memiliki beberapa pemicu untuk beberapa kasus yang seharusnya menandai alamat yang!
tidak layak apa pun tindakan Anda, Anda mungkin bahkan memicu itu beberapa kali untuk yang sama dan masih keluar dengan hasil yang sama.sed
tidak.Jawaban:
sed
API adalah primitif - dan ini adalah desain. Setidaknya, itu tetap primitif dengan desain - apakah itu dirancang secara primitif pada awal saya tidak bisa mengatakan. Dalam kebanyakan kasus, penulisansed
skrip yang, ketika dijalankan, akan menghasilkan skrip lainsed
memang masalah sederhana.sed
sangat sering diterapkan dengan cara ini oleh preprocessor makro sepertim4
dan / ataumake
.(Berikut ini adalah kasus penggunaan yang sangat hipotetis: ini adalah masalah yang direkayasa agar sesuai dengan solusi. Jika terasa seperti peregangan bagi Anda, maka itu mungkin karena itu, tetapi itu tidak selalu membuatnya kurang valid.)
Pertimbangkan file input berikut:
Jika kami ingin menulis
sed
skrip yang akan menambahkan kata -case ke ekor setiap kata yang sesuai dalam file input di atas hanya jika dapat ditemukan pada baris dalam konteks yang sesuai , dan kami ingin melakukannya seefisien mungkin ( sebagaimana seharusnya menjadi tujuan kita, misalnya, selama operasi kompilasi) maka kita harus memilih untuk menghindari penerapan/
regexp/
sebanyak mungkin.Satu hal yang mungkin kita lakukan adalah mengedit file di sistem kita sekarang, dan tidak pernah menelepon
sed
sama sekali selama kompilasi. Tetapi jika salah satu dari kata-kata dalam file tersebut harus atau tidak boleh dimasukkan berdasarkan pengaturan lokal dan / atau opsi waktu kompilasi, maka melakukan hal itu kemungkinan tidak akan menjadi alternatif yang diinginkan.Hal lain yang mungkin kita lakukan adalah memproses file sekarang melawan regexps. Kami dapat memproduksi - dan memasukkan dalam kompilasi kami - sebuah
sed
skrip yang dapat menerapkan pengeditan sesuai dengan nomor baris - yang biasanya merupakan rute yang jauh lebih efisien dalam jangka panjang.Sebagai contoh:
... yang menulis output dalam bentuk
sed
skrip dan yang terlihat seperti ...Ketika output itu disimpan ke file teks yang dapat dieksekusi pada mesin saya bernama
./bang.sed
dan jalankan seperti./bang.sed ./infile
, output adalah:Sekarang Anda mungkin bertanya kepada saya ... Mengapa saya ingin melakukan itu? Mengapa saya tidak hanya
grep
mencocokkan korek api? Lagi pula, siapa yang menggunakan case unta? Dan untuk setiap pertanyaan yang hanya bisa saya jawab, saya tidak tahu ... karena saya tidak tahu. Sebelum membaca pertanyaan ini, saya tidak pernah secara pribadi memperhatikan multi-! persyaratan parsing dalam spec - saya pikir ini adalah tangkapan yang cukup rapi.The multi! hal itu segera masuk akal bagi saya, meskipun - banyak
sed
spesifikasi diarahkan hanya diuraikan dan hanya dihasilkansed
skrip. Anda mungkin akan menemukan\n
pembatas ewline yang diperlukan untuk[wr:bt{]
lebih masuk akal dalam konteks itu, dan jika Anda mengingat gagasan itu, Anda mungkin lebih memahami beberapa aspek spesifikasi lainnya - (seperti:
tidak menerima alamat, danq
menolak untuk terima lebih dari 1) .Dalam contoh di atas saya menulis formulir tertentu
sed
naskah yang hanya pernah dibaca sekali. Jika Anda melihatnya dengan saksama, Anda mungkin memperhatikan bahwa ketikased
membaca file edit, ia berkembang dari satu blok perintah ke blok perintah berikutnya - ia tidak akan pernah bercabang dari atau menyelesaikan skrip-editnya sampai benar-benar selesai dengan file editnya.Saya menganggap itu multi-! alamat mungkin lebih berguna dalam konteks itu daripada di beberapa orang lain, tetapi, dalam kejujuran, saya tidak bisa memikirkan satu kasus di mana saya mungkin telah menggunakannya dengan sangat baik - dan saya
sed
banyak. Saya juga berpikir bahwa GNU / BSDsed
gagal untuk menanganinya seperti yang ditentukan - ini mungkin bukan aspek dari spesifikasi yang banyak diminati, jadi jika suatu implementasi mengabaikannya, saya ragu dengan sangat serius bug @ box mereka akan menderita hasilnya sangat buruk.Yang mengatakan, kegagalan untuk menangani ini sebagaimana ditentukan adalah bug untuk setiap implementasi yang berpura-pura kepatuhan, dan jadi saya pikir menembak email ke kotak dev yang relevan disebut-untuk di sini, dan saya bermaksud melakukannya jika Anda tidak melakukannya.
sumber
!
akan dihapus di spec berikutnya , apa yang terjadi di sini!