Cách thay thế một ký tự bằng một dòng mới trong Vim


1967

Tôi đang cố gắng thay thế từng ,tệp trong tệp hiện tại bằng một dòng mới:

:%s/,/\n/g 

Nhưng nó chèn những gì trông giống như một ^@thay vì một dòng mới thực sự. Các tập tin không ở chế độ DOS hoặc bất cứ điều gì.

Tôi nên làm gì?

Nếu bạn tò mò, như tôi, hãy kiểm tra câu hỏi Tại sao \ ra dòng mới cho Vim? cũng.


2
Stack Overflow là một trang web dành cho các câu hỏi lập trình và phát triển. Câu hỏi này dường như lạc đề vì nó không liên quan đến lập trình hay phát triển. Xem những chủ đề nào tôi có thể hỏi về đây trong Trung tâm trợ giúp. Có lẽ Super User hoặc Unix & Linux Stack Exchange sẽ là một nơi tốt hơn để hỏi.
jww

5
@jww câu hỏi này là 10 tuổi ... dường như quá cũ để di chuyển. Có rất nhiều câu hỏi như thế này, ví dụ: stackoverflow.com/questions/10175812/
Khăn

14
@jww vim là một công cụ thường được sử dụng cho các lập trình viên và các câu hỏi về các công cụ thường được sử dụng cho các lập trình viên là về chủ đề trong Stack Overflow . Mặc dù rõ ràng điều này phù hợp hơn trên Vi và Vim .
dùng202729

Câu trả lời:


2565

Sử dụng \rthay vì \n.

Thay thế bằng cách \nchèn một ký tự null vào văn bản. Để có được một dòng mới, sử dụng \r. Tuy nhiên, khi tìm kiếm một dòng mới, bạn vẫn sử dụng \n. Sự bất cân xứng này là do thực tế \n\r làm những điều hơi khác nhau :

\nkhớp với một dòng cuối (dòng mới), trong khi \rphù hợp với lợi nhuận vận chuyển. Mặt khác, trong các thay thế \nchèn một ký tự null trong khi \rchèn một dòng mới (chính xác hơn, nó được coi là đầu vào <CR>). Đây là một ví dụ nhỏ, không tương tác để minh họa điều này, bằng cách sử dụng tính năng dòng lệnh Vim (nói cách khác, bạn có thể sao chép và dán đoạn sau vào một thiết bị đầu cuối để chạy nó). xxdhiển thị một hexdump của tập tin kết quả.

echo bar > test
(echo 'Before:'; xxd test) > output.txt
vim test '+s/b/\n/' '+s/a/\r/' +wq
(echo 'After:'; xxd test) >> output.txt
more output.txt
Before:
0000000: 6261 720a                                bar.
After:
0000000: 000a 720a                                ..r.

Nói cách khác, \nđã chèn byte 0x00 vào văn bản; \rđã chèn byte 0x0a.


127
/ r được coi là nhấn phím Enter / Return. Nó hoạt động trên tất cả các nền tảng.
Luka Marinko


14
Tôi muốn điều này làm việc cho vi cổ điển. Trên AIX v6.1, \rkhông hoạt động như thế này. Nhưng bạn có thể nhấn Ctrl-V Enterthay cho việc gõ \r, và nó hoạt động.
eksortso

3
Tôi đến bữa tiệc muộn. Nếu \rchèn <CR>\nchèn null, làm thế nào tôi có thể thay thế một cái gì đó bằng trả lại xe ngựa?
Ông Llama

2
@SunnyRaj bạn có chắc về lịch sử của CR và LF không? Tôi có ấn tượng rằng ban đầu, LF di chuyển giấy về phía trước một lần nhưng không di chuyển đầu in và CR di chuyển đầu in nhưng không di chuyển giấy. Kết quả là, nếu HĐH của bạn không chuyển đổi đầu vào trước khi in, bạn không thể chỉ sử dụng LF hoặc CR để có được đầu ra chính xác. MS DOS đã sử dụng dữ liệu máy in thô làm định dạng tệp văn bản, Mac OS đã sử dụng CR và chuyển đổi từ định dạng đó sang định dạng thô của máy in và UNIX đã sử dụng LF và chuyển đổi từ định dạng đó sang định dạng thô của máy in.
Mikko Rantalainen

210

Đây là mẹo:

Đầu tiên, đặt phiên Vi (m) của bạn để cho phép khớp mẫu với các ký tự đặc biệt (ví dụ: dòng mới). Có lẽ đáng để đặt dòng này trong tệp .vimrc hoặc .exrc của bạn:

:set magic

Tiếp theo, làm:

:s/,/,^M/g

Để có được ^Mnhân vật, gõ Ctrl+ Vvà nhấn Enter. Trong Windows, làm Ctrl+ Q, Enter. Cách duy nhất tôi có thể nhớ những điều này là bằng cách nhớ chúng có ý nghĩa như thế nào:

Trả lời: Nhân vật điều khiển tồi tệ nhất sẽ sử dụng để thể hiện một dòng mới là gì?

B: Hoặc q(bởi vì nó thường có nghĩa là "Thoát") hoặc vbởi vì nó rất dễ gõ Ctrl+ Cdo nhầm lẫn và giết trình soạn thảo.

A: Làm cho nó như vậy.


9
Tôi đang sử dụng GVim trên Windows và tôi cũng không cần :set magic(nó cũng không có trong ~ / _vimrc) hoặc ctrl-q. Chỉ cần đơn giản ctrl-vtheo sau là enter tạo ra ^Mnhân vật cho tôi tốt.
Chris Phillips

5
Cv không đại diện cho một dòng mới; đó là lệnh "thoát nhân vật theo nghĩa đen". Tôi không biết Cv là một bản ghi nhớ cho một trong hai, nhưng có một lý do nó không phù hợp với bản đồ mới.
Jim Stewart

27
Ctrl-v là một bản ghi nhớ cho "nguyên văn" - tức là thoát khóa tiếp theo được nhấn vào mã khóa / ký tự "nguyên văn" của nó. Trong Windows, nó dán: để giữ cho mọi thứ quen thuộc. Ctrl-Q là dành cho "(un) Trích dẫn" có thể. Dù sao thì cũng khá ngu ngốc - nhưng bạn có thể sử dụng nó trong các tệp nhị phân - ví dụ: để tìm kiếm Ctrl-A thông qua Ctrl-Z (Tôi đoán là 1-26).
Tomasz Gandor

1
Ctrl-Ckhông thực sự giết trình soạn thảo, mặc dù nó có thể hủy bạn trở lại chế độ Bình thường. Ctrl-Vcó nghĩa là nguyên văn và Ctrl-Qcó nghĩa là ai đó đã mắc lỗi tải $VIMRUNTIME/mswin.vimtệp cấu hình. Bạn không cần mswin. Chỉ cần sử dụng vimrc của riêng bạn để thay thế.
00dani

Ôi thật là tuyệt vời. Tôi đã từng làm sed -n l cho đến bây giờ. Thật tốt khi biết rằng điều tương tự có thể đạt được với Ctrl-vtrong vim.
arpit

98

Trong cú pháp s/foo/bar, \r\ncó ý nghĩa khác nhau, tùy thuộc vào ngữ cảnh.


Ngắn:

Dành cho foo:

\ n = dòng mới (LF trên Linux / Mac, CR + LF trên Windows)
\ r = trả lại vận chuyển (CR)

Dành cho bar:

\ r = là dòng mới
\ n = null byte.

Dài hơn (với số ASCII):

NUL= 0x00 = 0 = Ctrl+ @
LF= 0x0A = 10 = Ctrl+ J
CR= 0x0D = 13 = Ctrl+M

Dưới đây là danh sách các ký tự điều khiển ASCII . Chèn chúng vào Vim qua Ctrl+ V, Ctrl+ ---key---.

Trong Bash hoặc các shell Unix / Linux khác, chỉ cần gõ Ctrl+ ---key---.

Hãy thử Ctrl+ Mtrong Bash. Nó cũng giống như đánh Enter, vì shell nhận ra ý nghĩa của nó, mặc dù các hệ thống Linux sử dụng nguồn cấp dữ liệu để phân định dòng.

Để chèn chữ theo nghĩa đen, việc thêm chúng bằng Ctrl+ Vcũng sẽ hoạt động.

Hãy thử trong Bash:

echo ^[[33;1mcolored.^[[0mnot colored.

Điều này sử dụng trình tự thoát ANSI . Chèn hai ^[thông qua Ctrl+ V, Esc.

Bạn cũng có thể thử Ctrl+ V, Ctrl+ M, Entersẽ cung cấp cho bạn cái này:

bash: $'\r': command not found

Ghi nhớ \rtừ trên? :>

Đây ASCII ký tự điều khiển danh sách là khác nhau từ một hoàn chỉnh bảng biểu tượng ASCII , trong đó các ký tự điều khiển, được đưa vào một giao diện điều khiển / pseudoterminal / Vim qua Ctrlchính (haha), có thể được tìm thấy ở đó.

Trong khi ở C và hầu hết các ngôn ngữ khác, bạn thường sử dụng mã bát phân để thể hiện các 'ký tự' này.

Nếu bạn thực sự muốn biết tất cả những thứ này đến từ đâu: TTY bị phá hủy . Đây là liên kết tốt nhất bạn sẽ bắt gặp về chủ đề này, nhưng hãy cẩn thận: Có những con rồng.


TL; DR

Thông thường foo= \n, và bar= \r.


1
Vì vậy, tôi tò mò làm thế nào bạn sẽ thay thế một nhân vật bằng một chiếc xe ngựa trở lại
codeshot

2
@codeshot :s/x/^M/gnên làm. Chèn ^Mthông qua ctrl-vtheo sau ctrl-m.
sjas

3
Cảm ơn sjas, Bạn biết câu hỏi này là một trong những điều kỳ lạ nhất mọi thời đại. 1008 phiếu bầu cho câu trả lời về cơ bản không nói gì hơn "vim làm những gì bạn tìm thấy. Đó là vì vim làm những gì bạn tìm thấy. Đừng bao giờ quên rằng vim làm những gì bạn tìm thấy." Tôi hy vọng sẽ tìm thấy một danh sách ngắn các mã cho các nhân vật thú vị trong mẫu, sự thay thế và lý do cho sự kỳ lạ để dễ nhớ và dự đoán sự kỳ lạ tương tự khác. Điều đó sẽ có được phiếu bầu của tôi.
codeshot

@codeshot một danh sách các nhân vật điều khiển ascii có thể giúp bạn. Xem cs.tut.fi/~jkorpela/chars/c0.html để tham khảo thêm. Tôi sẽ cập nhật câu trả lời của tôi để bao gồm hai liên kết.
sjas

55

Bạn cần sử dụng:

:%s/,/^M/g

Để có được ^Mnhân vật, nhấn Ctrl+ vtheo sau Enter.


4
Tôi phải làm <Cv> <Cm> để có được ký tự ^ M.
Jezen Thomas


24

Với Vim trên Windows, sử dụng Ctrl+ Qthay cho Ctrl+ V.


16

Đây là câu trả lời tốt nhất cho cách tôi nghĩ, nhưng nó sẽ đẹp hơn trong một bảng:

Tại sao \ ra dòng mới cho Vim?

Vì vậy, viết lại:

Bạn cần sử dụng \rđể sử dụng nguồn cấp dữ liệu (ASCII 0x0A, dòng mới Unix) trong thay thế regex, nhưng đó là đặc thù của thay thế - bạn thường nên tiếp tục sử dụng \ncho nguồn cấp dữ liệu và \rtrả lại vận chuyển.

Điều này là do Vim được sử dụng \nđể thay thế có nghĩa là ký tự NIL (ASCII 0x00). Bạn có thể đã mong đợi NIL \0thay vào đó, giải phóng \nviệc sử dụng thông thường cho nguồn cấp dữ liệu, nhưng \0đã có ý nghĩa trong việc thay thế regex, vì vậy nó đã được chuyển sang \n. Do đó, sau đó sẽ đi xa hơn để chuyển dòng mới từ \nsang \r(trong mô hình regex là ký tự hoàn trả vận chuyển, ASCII 0x0D).

Nhân vật | Mã ASCII | Đại diện C | Trận đấu chính thức | Thay thế Regex
------------------------- + ------------ + ----------- ------- + ------------- + ------------------------
không 0x00 | \ 0 | \ 0 | \ n
nguồn cấp dữ liệu (dòng mới Unix) | 0x0a | \ n | \ n | \ r
trở về vận chuyển | 0x0d | \ r | \ r | <không rõ>

NB: ^M( Ctrl+ V Ctrl+ Mtrên Linux) chèn một dòng mới khi được sử dụng trong thay thế regex thay vì trả lại vận chuyển như những người khác đã khuyên (tôi chỉ thử nó).

Cũng lưu ý rằng Vim sẽ dịch ký tự nguồn cấp dữ liệu khi lưu vào tệp dựa trên cài đặt định dạng tệp của nó và điều đó có thể gây nhầm lẫn.


11

Từ Eclipse , các ^Mký tự có thể được nhúng trong một dòng và bạn muốn chuyển đổi chúng thành dòng mới.

:s/\r/\r/g

8

Nhưng nếu người ta phải thay thế, thì điều sau đây hoạt động:

:%s/\n/\r\|\-\r/g

Ở trên, mỗi dòng tiếp theo được thay thế bằng dòng tiếp theo, và sau đó |-và một dòng mới. Điều này được sử dụng trong các bảng wiki.

Nếu văn bản như sau:

line1
line2
line3

Nó được đổi thành

line1
|-
line2
|-
line3

7

Nếu bạn cần làm điều đó cho toàn bộ tập tin, tôi cũng có thể đề nghị với bạn rằng bạn có thể thử từ dòng lệnh:

sed 's/\\n/\n/g' file > newfile

1
Lưu ý rằng điều này đòi hỏi GNU sed. Hãy thử printf 'foo\\nbar\n' | sed 's/\\n/\n/g'xem nó sẽ hoạt động trên hệ thống của bạn. (Tín dụng cho những người tốt của #bash trên freenode cho đề xuất này.)
Evan Donovan

Có, nhưng câu hỏi là về Vim. Có câu hỏi Stack Overflow Làm cách nào tôi có thể thay thế một dòng mới (\ n) bằng sed? .
Peter Mortensen

5

Đây là câu trả lời có hiệu quả với tôi. Từ anh chàng này:

---- trích dẫn Sử dụng trình soạn thảo vi để chèn char dòng mới thay thế


Một cái gì đó khác tôi phải làm và không thể nhớ và sau đó phải tìm kiếm.

Trong vi, để chèn một ký tự dòng mới vào tìm kiếm và thay thế, hãy làm như sau:

:%s/look_for/replace_with^M/g

Lệnh trên sẽ thay thế tất cả các phiên bản của look look_forR bằng cách thay thế_with \ nNH (với \ n có nghĩa là dòng mới).

Để nhận được ^ ^, hãy nhập tổ hợp phím Ctrl+ V, và sau đó (giải phóng tất cả các phím) nhấn Enterphím.


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.