Apa alasan untuk \ r dan \ n yang berarti berbagai hal dalam perintah s?

13

Kita semua tahu bahwa, ketika mencari, \nadalah baris baru dan \rcarriage return ( ^M), tetapi ketika mengganti \rbaris baru sedangkan \nbyte nol ( ^@).

Apa asal mula asimetri ini? Mengingat bahwa perilaku ini adalah ... aneh untuk sedikitnya (dan cukup kontraproduktif ketika Anda salah pertama kali) saya berharap ada beberapa alasan historis yang aneh.

(kebetulan, apakah ada cara untuk "memperbaiki" perilaku ini dan mendapatkan sesuatu yang lebih intuitif?)

Matteo Italia
sumber

Jawaban:

10

Pada tingkat paling dasar, sudah ada asimetri antara pencarian dan penggantian bagian :substitutekarena yang pertama adalah ekspresi reguler dan yang terakhir adalah teks, dengan urutan pelarian tambahan khusus . Ini hanya disorot oleh intuisi yang Anda miliki tentang apa \nartinya.

Misalnya, pertimbangkan bahwa \ndalam pencarian tidak cocok dengan literal \n. Cocok dengan akhir baris (EOL) urut byte, yang mungkin \r, \r\natau hanya \ntergantung pada 'fileformat'buffer.

Sejauh mengapa \rdigunakan untuk berarti "memasukkan EOL", ada beberapa sejarah di balik itu. Vi tidak punya cara untuk menangani byte NUL dalam file. Vim meningkatkannya dengan mengganti byte NUL dengan byte NL secara internal (karena string C dibatasi NUL).

Detail implementasi ini bocor ke dalam perilaku :substitutesejak \ndalam penggantian hanya dimasukkan ke representasi internal dari garis itu, yang digunakan untuk menunjukkan byte NUL. \rmenyisipkan EOL, memecah garis internal menjadi dua. Vim sebenarnya tidak menyimpan byte EOL dalam memori, sebagai gantinya (de) membuat cerita bersambung saat membaca / menulis buffer.

Itu tidak dapat diubah sekarang tanpa melanggar banyak skrip dan memori otot banyak pengguna. Untungnya, ini sudah didokumentasikan :help sub-replace-special.

jamessan
sumber
6

Sebuah NULbyte adalah terminator string dalam C, dan untuk alasan ini Vim menggunakan konvensi ini, dijelaskan dalam manual di :h NL-used-for-Nul:

<Nul> karakter dalam file disimpan sebagai <NL> dalam memori. Di layar mereka ditampilkan sebagai "^ @". Terjemahan dilakukan ketika membaca dan menulis file. Untuk mencocokkan <Nul> dengan pola pencarian Anda cukup memasukkan CTRL- @ atau "CTRL-V 000". Ini mungkin hanya apa yang Anda harapkan. Secara internal karakter diganti dengan <NL> dalam pola pencarian. Yang tidak biasa adalah mengetik CTRL-V CTRL-J juga menyisipkan <NL>, sehingga juga mencari <Nul> dalam file. {Vi tidak bisa menangani karakter <Nul> dalam file sama sekali}

Konvensi ini telah menyebar ke :s/.../.../perintah, tetapi tidak ke substitute()fungsi. \rdan \nsebagai pengganti string dalam substitute()panggilan mempertahankan makna aslinya.

Saya tidak berpikir ada alasan yang lebih dalam untuk perilaku tersebut. Vim telah berevolusi secara organik dari aslinya vi. Tidak pernah ada cetak biru besar untuk itu, fitur hanya ditumpuk di atas satu sama lain, dengan upaya yang relatif sedikit untuk menjaga mereka terorganisir.

Sato Katsura
sumber
0

Klon Vi lainnya tidak mendukung \ratau \n(sebagai backslash dan huruf nyata) dalam substitusi, tetapi perilaku real ^M( CTRL-V Enter) yang berarti membagi garis menjadi dua baris adalah perilaku standar :

Memasukkan <carriage-return> di repl (yang membutuhkan pelarian <backslash> dalam mode ex dan pelolosan <control> -V dalam mode terbuka atau vi ) akan membagi garis pada titik itu, membuat baris baru di buffer penyuntingan . <carriage-return> harus dibuang.

Dalam arsip Unix History, versi pertama BSD ex / vi yang muncul adalah 4.1cBSD ( @(#)ex_re.c 7.2 10/16/81, dan tidak ada dalam 4BSD ( @(#)ex_re.c 6.2 10/23/80) [4.1a dan 4.1b tidak ada dalam arsip].

Kode yang relevan adalah:

/* ^V <return> from vi to split lines */
if (c == '\r')
    c = '\n';

Ini juga disebutkan dalam file berita :

Sekarang dimungkinkan untuk membagi baris dengan perintah pengganti dari vi, dengan menggunakan ^ V <return> di rhs. Ini menangani alasan bagus terakhir untuk menggunakan mode perintah ex.

Perilaku yang sebelumnya didukung dalam mode perintah ex adalah untuk backslash-enter (yaitu backslash diikuti oleh baris nyata) untuk memasukkan baris baru.

Random832
sumber
0

Asal usul asimetri kembali ke jalan sejarah komputasi.

Versi pendek:

<CR> & <LF>  (Carriage-Return and Linefeed) 
== 
\r & \n

Versi panjang:
Layar pertama pada dasarnya adalah versi digital dari teletype (TTY) dan menggunakan kode kontrol untuk menghasilkan perilaku yang mirip dengan printer. Carriage-return membawa kursor (atau print-head) ke kolom awal. Linefeed maju ke baris berikutnya (pada layar) dan mengumpankan kertas ke depan satu baris.

Untuk printer, Anda harus melakukan paired <CR><LF>atau output Anda tidak akan terlihat benar. Di layar awal, masalah ini masih berlaku.

DOS (dan agak-Windows setelah) mengikuti standar lama dan menyimpan teks <CRLF>.

* Teks NIX (karena sebagian besar pengguna sudah terbiasa) hanya menggunakan <LF>untuk efisiensi.

Untuk menguji di Windows, gunakan Word / Wordpad dan simpan beberapa baris teks "as type: Text - MS-DOS format". Kemudian buka file yang sama di Notepad. Seharusnya terlihat normal. Kemudian simpan file yang sama di Word / Wordpad "as type: Text". Notepad akan mengabaikan semua baris baru dan menjalankan baris bersama. [Format teks Notepad default untuk \r\nkombinasi sementara Word / Wordpad default ke \n.]

adalah kode yang setara dengan <CR>

\ n adalah kode yang setara dengan <LF>

Dan dalam pengalaman saya (sangat terbatas) dengan vi, ia akan mencoba untuk "memperbaiki" <CRLF>kombinasi dari editor teks DOS saya. vi akhirnya menghapus satu karakter, menggantikan dengan <NUL>. Sebagian besar alasan saya berhenti menggunakan vi.

Robin
sumber
2
Meskipun semua informasi Anda menarik, itu hanya memberi tahu mengapa \rada <CR>dan tidak \nada <LF>. Itu tidak membahas pertanyaan aktual mengapa \n\rberperilaku berbeda dalam konteks yang berbeda.
Tumbler41
Terima kasih! :-) Saya mengubahnya ketika Anda menjawab. (Menambahkan paragraf terakhir.)
Robin