mengenai portable sed -e… db or! b?


12

Dalam pengeditan ini Stéphane Chazelas POSIXifies (lagi)sed format saya dengan memasukkan -eistirahat xpression dan -epernyataan xpression lain . Sekarang, saya mungkin hanya bertanya kepadanya mengapa dalam komentar, saya kira, tetapi sudah revisi nomor 18 pada jawaban itu dan hampir semua yang sebelumnya sudah berkat freebies serupa (jika Anda dapat melihat komentar yang dihapus Anda akan tahu apa Maksud saya) . Juga, saya pikir saya cukup dekat untuk memahami mengapa mengucapkan ini dengan cara yang mungkin lebih bermanfaat secara umum. Jadi, inilah harapan ...

Saya biasanya lebih suka menjaga total sed -expressions saya menjadi satu jika saya bisa, tetapi saya juga memiliki preferensi yang lebih besar untuk menyesuaikan dengan spesifikasi sedekat mungkin, terutama ketika perbedaannya tidak lebih dari a <space>dan a -e. Tetapi saya tidak dapat melakukan ini jika saya tidak mengerti mengapa saya harus melakukannya. Berikut ini ikhtisar singkat dari pemahaman saya saat ini:

  • yang ' -e 'istirahat portable dapat berdiri di untuk sednaskah \nistirahat ewline dalam sedpernyataan command-line ... Aku memang kabur tentang mengapa

  • kurung kurawal dalam suatu sed {fungsi }harus didahului dengan \njeda baris seperti yang dinyatakan di sini:

    • Ini <right-brace>harus didahului oleh a <newline>dan dapat didahului atau diikuti oleh <blank>karakter.
  • sebuah \nistirahat ewline juga sama diperlukan berikut setiap penggunaan ... a, b, c, i, r, t, w, atau :.

Tapi saya tidak mengerti dengan jelas bagaimana definisi {fungsi }berhubungan dengan !operator yang tidak. Satu-satunya penyebutan yang saya temukan dari operator negasi di negara bagian spesifikasi:

  • Fungsi dapat didahului oleh satu atau lebih !karakter, dalam hal ini fungsi tersebut akan diterapkan jika alamat tidak memilih ruang pola.

Apakah ini berarti bahwa penggunaan kawat gigi !menyiratkan ? Bagaimana dengan perintah - haruskah mereka juga dipisahkan oleh istirahat? Apakah ini yang dialamatkan ketika Stéphane baru-baru ini MEMPIPTAKAN jawaban saya?{}$!' -e '

Saya pikir itu adalah !operator negasi, atau itu adalah bpernyataan peternakan yang ia alamatkan dalam editnya - atau mungkin keduanya sekaligus - tetapi saya tidak tahu dan ingin melakukannya. Jika hanya satu bpernyataan peternakan, maka saya yakin suatu dakan lakukan di tempat dan menghilangkan kebutuhan untuk ' -e 'istirahat, tapi aku lebih suka menjadi tertentu sebelum hazarding sebuah tiga kali POSIXified jawaban. Bisakah kamu menolong?

Saya melakukan mengambil risiko itu setelah semua , tapi tidak dengan pasti besar ...


Dengan b;n;:b, Anda bercabang ke label yang disebut ";n;:b"sed historis dan POSIX (dan sed GNU tidak dalam hal itu).
Stéphane Chazelas

@ StéphaneChazelas - Saya mendapatkan :bagiannya - Anda menyetir pulang beberapa bulan yang lalu. Tapi saya tidak sepenuhnya mengerti mengapa sedperintah kedua juga POSIXified .
mikeserv

1
Bagaimanapun, spesifikasi POSIX sedsangat tidak jelas bagi saya. Saya telah meminta klarifikasi beberapa kali di masa lalu, tetapi saya rasa itu tidak diperbarui. Tes yang baik adalah dengan mencoba dengan heirloom toolchest (Solaris one, berasal dari aslinya dan yang menjadi dasar spesifikasi POSIX).
Stéphane Chazelas

1
@syntaxerror - saya tidak percaya itu masalahnya sama sekali. jika Anda membaca spec Anda akan menemukan bahwa s///ubstitutions khusus untuk menerima rantai dengan ; . itu menjadi kabur di sekitar perintah yang harus dibatasi dengan baris baru dan bagaimana -ebisa bertahan dalam kasus itu - setidaknya itu berlaku untuk saya. Namun saya belum tersandung pada sedyang tidak menafsirkan mereka cukup dipertukarkan sekalipun.
mikeserv

1
@syntaxerror - Saya suka, tetapi Anda harus tahu bahwa Anda tidak perlu ;sebelum baris baru - baris baru baik-baik saja. Jujur, Anda bisa melakukannya tanpa -edan semuanya sepenuhnya dan hanya menulis file seperti #!/bin/seddengan setiap perintah pada baris baru - atau orang-orang yang tidak memerlukan pembatas seperti itu malah dipisahkan ;. Orang-orang yang melakukan memerlukan baris biasanya orang-orang yang mengambil input sewenang-wenang - :nama label dan perintah yang merujuk kepada mereka seperti batau tatau menutup }curlies untuk fungsi, atau rbenar-benar menyebalkan dan writual yang mengambil args nama file. Mereka semua perlu diikuti \n.
mikeserv

Jawaban:


4

Jadi sudah saatnya pertanyaan ini dijawab, dan, meskipun saya akhirnya secara intuitif menemukan cara untuk melakukan ini dengan benar di hampir setiap kasus beberapa waktu lalu, saya baru-baru ini berhasil mengonkretkan pemahaman dengan teks dalam standar. . Itu sebenarnya dinyatakan di sana cukup sederhana - Aku hanya bodoh mengabaikannya berkali-kali, kurasa.

Bagian-bagian yang relevan dari teks semuanya ditemukan di bawah judul ...

  • Perintah Pengeditan dised :

    • Teks argumen harus terdiri dari satu atau lebih baris. Setiap \ngaris tepi yang disematkan dalam teks harus didahului dengan \garis miring terbalik. Garis miring terbalik lainnya dalam teks harus dihapus, dan karakter berikut harus diperlakukan secara harfiah.

    • The rdan wkata kerja perintah, dan wbendera ke sperintah, mengambil opsional RFILE (atau wfile ) parameter, dipisahkan dari kata kerja perintah surat atau flag oleh satu atau lebih <blank>s; implementasi dapat memungkinkan pemisahan nol sebagai perpanjangan.

    • Perintah verba selain {, a, b, c, i, r, t, w, :, dan #dapat diikuti oleh ;koma, opsional <blank>s, dan kata kerja perintah lain. Namun, ketika skata kerja perintah digunakan dengan wbendera, mengikutinya dengan perintah lain dengan cara ini menghasilkan hasil yang tidak ditentukan.

...di...

  • Opsi: Beberapa -edan -fopsi dapat ditentukan. Semua perintah harus ditambahkan ke skrip dalam urutan yang ditentukan, terlepas dari asalnya.

    • -e script - Tambahkan perintah pengeditan yang ditentukan oleh argumen opsi- skrip ke akhir skrip perintah pengeditan. The Script pilihan-argumen harus memiliki sifat-sifat yang sama dengan naskah operan, dijelaskan dalam operan bagian.

    • -f script_file - Tambahkan perintah pengeditan di file script_file ke akhir skrip.

Dan terakhir di ...

  • Operan:

    • script - String yang akan digunakan sebagai skrip perintah pengeditan. Aplikasi tidak akan menyajikan skrip yang melanggar pembatasan file teks kecuali bahwa karakter terakhir tidak harus \newline.

Jadi, ketika Anda mengambilnya sama sekali, masuk akal bahwa setiap perintah yang secara opsional diikuti oleh parameter arbitrer tanpa pembatas yang telah ditentukan (sebagai lawan s d sub d repl d flagmisalnya) harus membatasi pada \newline yang tidak terhindar.

Dapat diperdebatkan bahwa itu ; adalah pembatas yang telah ditentukan tetapi dalam kasus menggunakan perintah ;untuk salah satu [aic]akan mengharuskan parser terpisah dimasukkan dalam implementasi khusus untuk tiga perintah - terpisah, yaitu, dari parser yang digunakan untuk [:brw], misalnya. Atau implementasi harus mengharuskan backslash ; juga lolos dalam parameter teks dan hanya tumbuh lebih rumit dari sana.

Jika saya menulis sesuatu sedyang saya inginkan sesuai dan efisien, maka saya tidak akan menulis parser yang terpisah, saya harapkan - kecuali bahwa mungkin [aic]harus membuat kesalahan sintaks jika tidak segera diikuti oleh \newline. Tapi itu adalah masalah tokenization sederhana - kasus pembatas akhir umumnya yang lebih bermasalah. Saya hanya akan menuliskannya demikian:

sed -e w\ file\\ -e one -e '...;and more commands'

...dan...

sed -e a\\ -e appended\\ -e text -e '...;and more commands'

... akan berperilaku sangat mirip, karena yang pertama akan membuat dan menulis ke file bernama:

file
one

... dan yang kedua akan menambahkan blok teks ke baris saat ini pada output seperti ...

appended
text

... karena keduanya akan berbagi kode parsing yang sama untuk parameter.

Dan mengenai { ... }dan $!masalah - yah, saya jauh dari sana. Perintah tunggal yang didahului oleh alamat bukanlah fungsi melainkan perintah yang ditujukan. Hampir semua perintah - termasuk { definisi fungsi } ditentukan untuk menerima /one/atau /one/,/two/alamat - dengan pengecualian #komentar dan :definisi label . Dan sebuah alamat dapat berupa nomor baris atau express biasa dan dapat dinegasikan dengan !. Jadi semuanya ...

$!d
/address/s/ub/stitution/
5!y/d/c/

... dapat diikuti oleh ;lebih banyak perintah sesuai dengan standar, tetapi jika lebih banyak perintah diperlukan untuk satu alamat, dan alamat itu tidak harus dievaluasi ulang mengikuti eksekusi setiap perintah, maka suatu {fungsi }harus digunakan seperti:

/address/{ s//replace addressed pattern/
           s/do other conditional/substitutions/
           s/in the same context/without/
           s/reevaluating/address/
}

... di mana {tidak dapat diikuti pada baris yang sama dengan penutupan }dan bahwa penutupan }tidak dapat terjadi kecuali pada awal garis. Tetapi jika perintah yang terkandung seharusnya tidak diikuti oleh \newline, maka perintah tersebut tidak harus berada dalam fungsi juga. Jadi semua s///ubstitutions di atas - dan bahkan }kurung kurawal, dapat dengan mudah diikuti oleh ;titik koma dan perintah lebih lanjut.

Saya terus berbicara tentang \npembatas ewline tetapi pertanyaannya adalah tentang -epernyataan xpression, saya tahu. Tapi keduanya benar-benar satu dan sama, dan hubungan utamanya adalah bahwa skrip dapat berupa argumen baris perintah literal atau file dengan salah satu -[ef], dan keduanya ditafsirkan sebagai file teks (yang ditentukan untuk diakhiri dengan \newline) tetapi keduanya tidak perlu diakhiri dengan \newline. Dengan ini saya bisa reasonbly (saya berharap) mengambil kesimpulan bahwa \0NULargumen dibatasi menyiratkan berakhir \newline, dan karena semua argumen doa mendapatkan setidaknya) sebuah \0NULpembatas pula, maka baik harus bekerja dengan baik.

Bahkan, dalam prakteknya, dalam setiap kasus kecuali satu di mana standar menentukan \backslash lolos dari baris baru harus diminta, saya telah menemukan ...

sed -e ... -e '...\' -e '...'

... bekerja dengan baik juga. Dan dalam setiap kasus - sekali lagi, dalam praktik - di mana \newline yang tidak lolos harus diminta ...

sed -e '...' -e '...'

... telah bekerja untuk saya juga. Satu-satunya pengecualian yang saya sebutkan di atas adalah ...

sed -e 's/.../...\' -e '.../'

... yang tidak berfungsi untuk implementasi apa pun di salah satu pengujian saya. Saya cukup yakin bahwa jatuh kembali ke persyaratan file teks dan fakta yang s/// datang dengan pembatas dan jadi tidak ada alasan pernyataan tunggal harus span \0NULargumen dibatasi.

Jadi, sebagai kesimpulan, berikut adalah ikhtisar singkat cara portabel untuk menulis beberapa jenis sedperintah:

Untuk salah satu dari [aic]:

...commands;[aic]\
text embedded newline\
delimiting newline
...more;commands...

...atau...

sed -e '...commands;[aic]\' -e 'text embedded newline\' -e 'delimiting newline' -e '.;.;.'

Untuk setiap dari [:rwtb]mana parameter adalah opsional (untuk semua tapi :) tetapi pembatasan \newline adalah tidak . Perhatikan bahwa saya tidak pernah memiliki alasan untuk mencoba beberapa parameter label baris seperti yang akan digunakan [:tb], tetapi bahwa writing / reading ke beberapa baris dalam parameter file [rw] biasanya diterima tanpa pertanyaan oleh seds. Saya telah menguji selama embedded \newline lolos dengan \backslash. Namun, standar tidak secara langsung menentukan bahwa label dan parameter file [rw] harus diuraikan secara identik ke teksparameter dan tidak menyebutkan \newline tentang dua yang pertama kecuali karena membatasi mereka.

...commands;[:trwb] parameter
...more;commands...

...atau...

sed -e '[:trwb] parameter' -e '...'

... di mana di <space>atas adalah opsional untuk [:tb].

Dan terakhir...

...;address[!]{ ...function;commands...
};...more;commands....

...atau...

sed -e '...;address[!]{ ...function;commands...' -e '};...more;commands...'

... di mana salah satu perintah yang disebutkan di atas (kecuali :) juga menerima setidaknya satu alamat dan yang dapat berupa /regexp /atau nomor baris dan dapat dinegasikan dengan !, tetapi jika lebih dari satu perintah diperlukan untuk satu evaluasi alamat maka kurung {fungsi }pembatas konteks fungsi harus digunakan. Suatu fungsi dapat berisi bahkan beberapa \nperintah yang dibatasi ewline, tetapi masing-masing harus dibatasi di dalam kurung kurawal seperti yang seharusnya.

Dan itulah cara menulis sedskrip portabel .


2
Mengapa Anda tidak menerima jawaban Anda sendiri?
Philippos
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.