How to replace a character by a newline in Vim

vim replace escaping newline vi

736248 просмотра

11 ответа

I'm trying to replace each , in the current file by a new line:

:%s/,/\n/g 

But it inserts what looks like a ^@ instead of an actual newline. The file is not in DOS mode or anything.

What should I do?

If you are curious, like me, check the question Why is \r a newline for Vim? as well.

Автор: Vinko Vrsalovic Источник Размещён: 07.10.2019 09:24

Ответы (11)


2404 плюса

Решение

Use \r instead of \n.

Substituting by \n inserts a null character into the text. To get a newline, use \r. When searching for a newline, you’d still use \n, however. This asymmetry is due to the fact that \n and \r do slightly different things:

\n matches an end of line (newline), whereas \r matches a carriage return. On the other hand, in substitutions \n inserts a null character whereas \r inserts a newline (more precisely, it’s treated as the input ). Here’s a small, non-interactive example to illustrate this, using the Vim command line feature (in other words, you can copy and paste the following into a terminal to run it). xxd shows a hexdump of the resulting file.

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.

In other words, \n has inserted the byte 0x00 into the text; \r has inserted the byte 0x0a.

Автор: Konrad Rudolph Размещён: 16.09.2008 11:21

194 плюса

Here's the trick:

First, set your vi(m) session to allow pattern matching with special characters (ie: newline). It's probably worth putting this line in your .vimrc or .exrc file.

:set magic

Next, do:

:s/,/,^M/g

To get the ^M character, type Control-v and hit Enter. Under Windows, do Control-q, Enter. The only way I can remember these is by remembering how little sense they make:

A: What would be the worst control-character to use to represent a newline?

B: Either q (because it usually means "Quit") or v because it would be so easy to type Control-c by mistake and kill the editor.

A: Make it so.

Автор: Logan Размещён: 25.09.2008 11:40

90 плюса

In the syntax s/foo/bar \r and \n have different meanings, depending on context.


short:

For foo:
\n = newline (LF on linux/mac, CRLF on windows)
\r = carriage return (CR)

For bar:
\r = is newline
\n = null byte.

longer: (with ascii numbers)

NUL = 0x00 = 0 = CTRL@
LF = 0x0A = 10 = CTRLJ
CR = 0x0D = 13 = CTRLM

Here is a list of the ASCII control characters, insert them in vim via CTRLvCTRL---key---.
In bash or the other unix/linux shells just type CTRL---key---. Try CTRLM in bash, its the same as hitting ENTER, as the shell realizes what is meant, even though linux systems use Line Feeds for line delimiting.

To insert literal's in bash, prepending them with CTRLv will also work.

Try in bash:

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

This uses ANSI escape sequences, insert the two ^['s via CTRLvESC.

You might also try CTRLvCTRLmENTER, which will give you this:

bash: $'\r': command not found

Remember the \r from above? :>

This ASCII control characters list is different from a complete ASCII symbol table, in that the control characters, which are inserted into a console/pseudoterminal/vim via the CTRL key (haha), can be found there. Whereas in C and most other languages you usually use the octal codes to represent these 'characters'.

If you really want to know where all this comes from: http://www.linusakesson.net/programming/tty/.
This is the best link you will come across about this topic, but beware: There be dragons.


TL;DR

Usually foo = \n, and bar = \r.

Автор: sjas Размещён: 23.09.2013 02:00

50 плюса

You need to use

:%s/,/^M/g

To get the ^M character, press Ctrl v followed by Enter

Автор: dogbane Размещён: 16.09.2008 11:30

36 плюса

\r can do the work here for you.

Автор: Lasar Размещён: 16.09.2008 11:21

23 плюса

With Vim on Windows use Ctrl+Q in place of Ctrl+V

Автор: grantc Размещён: 16.09.2008 11:45

10 плюса

This is the best answer for the way I think but it would have been nicer in a table: https://stackoverflow.com/a/12389839/962394.

So, rewording:

You need to use \r to use a line feed (ascii 0x0a, the unix newline) in a regex replacement but that is peculiar to the replacement - you should normally continue to expect to use \n for line feed and \r for carriage return.

This is because vim used \n in a replacement to mean the NIL character (ascii 0x00). You might have expected NIL to have been \0 instead, freeing \n for its usual use for line feed, but \0 already has a meaning in regex replacements so it was shifted to \n. Hence then going further to also shift the newline from \n to \r (which in a regex pattern is the carriage return character, ascii 0x0d).

character                | ascii code | C representation | regex match | regex replacement
-------------------------+------------+------------------+-------------+------------------------
nil                      | 0x00       | \0               | \0          | \n
line feed (unix newline) | 0x0a       | \n               | \n          | \r
carriage return          | 0x0d       | \r               | \r          | 

NB: ^M (Ctrl-V Ctrl-M on linux) inserts a newline when used in a regex replacement rather than a carriage return as others have advised (I just tried it).

Also note that vim will translate the line feed character when it saves to file based on its file format settings and that might confuse matters.

Автор: codeshot Размещён: 08.04.2015 12:15

10 плюса

From eclipse, the ^M characters can be embedded in a line, and you want to convert them to newlines.

:s/\r/\r/g
Автор: rickfoosusa Размещён: 06.09.2011 05:53

7 плюса

But if one has to substitute then following thing works

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

in the above every next line is substituted with next line and then |- and again a next line. This is used in wiki tables. if the text is as follows:

line1
line2
line3

is changed to

line1
|-
line2
|-
line3
Автор: Kiran K Telukunta Размещён: 07.02.2012 08:09

6 плюса

If you need to do for a whole file, it was also suggested to me that you could try from the command line

sed 's/\\n/\n/g' file > newfile
Автор: Evan Donovan Размещён: 09.02.2012 11:01

4 плюса

Heres the answer that worked for me. From this guy

----quoting http://jaysonlorenzen.wordpress.com/2009/04/28/use-vi-editor-to-insert-newline-char-in-replace/


Something else I have to do and cannot remember and then have to look up.

In vi to insert a newline character in a search and replace, do the following:

:%s/look_for/replace_with^M/g the command above would replace all instances of “look_for” with “replace_with\n” (with \n meaning newline)

to get the “^M”, enter the key combination “ctl-V” then after that (release all keys) press the “enter” key.


Автор: user407749 Размещён: 03.02.2012 07:31
32x32