Lý do cho \ r và \ n có nghĩa là những thứ khác nhau trong lệnh s là gì?


13

Chúng ta đều biết rằng, khi tìm kiếm, \nlà dòng mới và là dòng \rtrả về ( ^M), nhưng khi thay thế \rlà dòng mới trong khi \nlà byte byte ( ^@).

Nguồn gốc của sự bất đối xứng này là gì? Cho rằng hành vi này là ... đặc biệt để nói rằng ít nhất (và khá phản tác dụng khi bạn hiểu sai lần đầu tiên) Tôi hy vọng có một số lý do lịch sử kỳ lạ.

(tình cờ, có cách nào đó để "sửa chữa" hành vi này và có được thứ gì đó trực quan hơn không?)

Câu trả lời:


10

Ở cấp độ cơ bản nhất, đã có sự bất cân xứng giữa các phần tìm kiếm và thay thế :substitutebởi vì phần trước là biểu thức chính quy và phần sau là văn bản, với các chuỗi thoát bổ sung cụ thể . Điều này chỉ được nhấn mạnh bởi trực giác bạn có về những gì \ncó nghĩa là.

Ví dụ, hãy xem xét rằng \ntrong tìm kiếm không khớp với nghĩa đen \n. Nó phù hợp với kết thúc chuỗi byte dòng (EOL), có thể \r, \r\nhay chỉ \nphụ thuộc vào 'fileformat'của bộ đệm.

Theo như lý do tại sao \rđược sử dụng có nghĩa là "chèn EOL", có một số lịch sử đằng sau đó. Vi không có cách nào để xử lý một byte NUL trong một tệp. Vim đã cải thiện điều đó bằng cách thay thế các byte NUL bằng một byte NL bên trong (vì các chuỗi C được phân định bằng NUL).

Chi tiết triển khai này bị rò rỉ vào hành vi của :substitute\ntrong thay thế chỉ đơn giản được chèn vào biểu diễn bên trong của dòng đó, được sử dụng để chỉ ra một byte NUL. \rchèn một EOL, phá vỡ dòng nội bộ thành hai. Vim không thực sự lưu trữ các byte EOL trong bộ nhớ, thay vào đó (de) tuần tự hóa chúng khi đọc / ghi bộ đệm.

Bây giờ không thể thay đổi mà không phá vỡ nhiều tập lệnh và bộ nhớ cơ của nhiều người dùng. Rất may, nó được ghi lại trong :help sub-replace-special.


6

Một NULbyte là một bộ kết thúc chuỗi trong C và vì lý do này, Vim sử dụng quy ước này, được mô tả trong hướng dẫn tại :h NL-used-for-Nul:

Các ký tự <Nul> trong tệp được lưu dưới dạng <NL> trong bộ nhớ. Trong màn hình, chúng được hiển thị là "^ @". Bản dịch được thực hiện khi đọc và ghi tập tin. Để khớp <Nul> với mẫu tìm kiếm, bạn chỉ cần nhập CTRL- @ hoặc "CTRL-V 000". Đây có lẽ chỉ là những gì bạn mong đợi. Bên trong nhân vật được thay thế bằng <NL> trong mẫu tìm kiếm. Điều bất thường là gõ CTRL-V CTRL-J cũng chèn <NL>, do đó cũng tìm kiếm <Nul> trong tệp. {Vi không thể xử lý các ký tự <Nul> trong tệp}

Quy ước này đã tràn qua :s/.../.../lệnh, nhưng không phải cho substitute()chức năng. \r\ntrong chuỗi thay thế trong substitute()các cuộc gọi giữ ý nghĩa ban đầu của chúng.

Tôi không nghĩ rằng có những lý do sâu sắc hơn cho một trong hai hành vi. Vim chỉ đơn giản là phát triển hữu cơ từ bản gốc vi. Không bao giờ có bất kỳ kế hoạch chi tiết lớn nào cho nó, các tính năng chỉ được xếp chồng lên nhau, với rất ít nỗ lực để giữ cho chúng được tổ chức.


0

Các bản sao Vi khác không hỗ trợ \rhoặc \n(như một dấu gạch chéo ngược và chữ cái thực) thay thế, nhưng hành vi của một thực ^M( CTRL-V Enter) có nghĩa là chia dòng thành hai dòng là hành vi tiêu chuẩn :

Nhập < car car -return> vào thay thế (yêu cầu thoát <backslash> ở chế độ ex và thoát <control> -V ở chế độ mở hoặc vi ) sẽ phân chia dòng tại điểm đó, tạo một dòng mới trong bộ đệm chỉnh sửa . <Vận chuyển trở lại> sẽ bị loại bỏ.

Trong kho lưu trữ Lịch sử Unix, phiên bản đầu tiên của BSD ex / vi mà nó xuất hiện là 4.1cBSD ( @(#)ex_re.c 7.2 10/16/81và không có trong 4BSD ( @(#)ex_re.c 6.2 10/23/80) [4.1a và 4.1b không có trong kho lưu trữ].

Mã liên quan là:

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

Điều này cũng được đề cập trong các tập tin tin tức :

Bây giờ có thể phân chia các dòng bằng các lệnh thay thế từ vi, bằng cách sử dụng ^ V <return> trong rhs. Điều này quan tâm đến lý do tốt cuối cùng để sử dụng chế độ lệnh ex.

Hành vi được hỗ trợ trước đó trong chế độ lệnh ex là cho dấu gạch chéo ngược (nghĩa là dấu gạch chéo ngược theo sau là một dòng mới thực sự) để chèn một dòng mới.


0

Nguồn gốc của sự bất đối xứng quay trở lại một cách vào lịch sử điện toán.

Phiên bản ngắn:

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

Phiên bản dài:
Các màn hình đầu tiên về cơ bản là các phiên bản kỹ thuật số của teletypes (TTY) và được sử dụng mã điều khiển để tạo ra hành vi tương tự với máy in. Vận chuyển trở lại đã đưa con trỏ (hoặc đầu in) vào cột bắt đầu. Linefeed tiến tới hàng tiếp theo (trên màn hình) và đưa giấy về phía trước một dòng.

Đối với máy in, bạn phải thực hiện ghép nối <CR><LF>hoặc đầu ra của bạn sẽ không đúng. Trên màn hình sớm, vấn đề vẫn được giữ đúng.

DOS (và sorta-Windows sau) tuân theo tiêu chuẩn cũ và lưu văn bản với <CRLF>.

* Văn bản NIX (vì hầu hết người dùng vi quen thuộc) chỉ sử dụng <LF>cho hiệu quả.

Để kiểm tra trong Windows, hãy sử dụng Word / Wordpad và lưu một vài dòng văn bản "dưới dạng: Văn bản - định dạng MS-DOS". Sau đó mở cùng một tệp trong Notepad. Nó sẽ trông bình thường. Sau đó lưu cùng một tệp trong Word / Wordpad "dưới dạng: Văn bản". Notepad sẽ bỏ qua tất cả các dòng mới và chạy các dòng với nhau. [Định dạng văn bản của Notepad mặc định là \r\nkết hợp trong khi Word / Wordpad mặc định thành \n.]

\ r là mã tương đương với <CR>

\ n là mã tương đương với <LF>

Và theo kinh nghiệm (rất hạn chế) của tôi với vi, nó sẽ cố gắng "sửa" sự <CRLF>kết hợp từ trình soạn thảo văn bản DOS của tôi. cuối cùng vi loại bỏ một ký tự, thay thế bằng <NUL>. Một phần lớn lý do tôi đã ngừng sử dụng vi.


2
Trong khi tất cả thông tin của bạn là thú vị, nó chỉ cho biết tại sao \r<CR>\n<LF>. Nó không giải quyết câu hỏi thực tế tại sao \n\rhành xử khác nhau trong các bối cảnh khác nhau.
Tumbler41

Cảm ơn bạn! :-) Tôi đã thay đổi nó khi bạn trả lời. (Đã thêm đoạn cuối.)
Robin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.