Cómo reemplazar un personaje por una nueva línea en Vim


1967

Estoy tratando de reemplazar cada uno ,en el archivo actual por una nueva línea:

:%s/,/\n/g 

Pero inserta lo que parece ^@una nueva línea en lugar de una nueva línea real. El archivo no está en modo DOS ni nada.

¿Qué tengo que hacer?

Si tiene curiosidad, como yo, consulte la pregunta ¿Por qué es \ ra nueva línea para Vim? también.


2
Stack Overflow es un sitio para preguntas de programación y desarrollo. Esta pregunta parece estar fuera de tema porque no se trata de programación o desarrollo. Consulte los temas sobre los que puedo preguntar aquí en el Centro de ayuda. Quizás Super User o Unix & Linux Stack Exchange sería un mejor lugar para preguntar.
jww

55
@jww esta pregunta tiene 10 años ... parece ser demasiado vieja para migrar. Hay muchas preguntas como esta, por ejemplo: stackoverflow.com/questions/10175812/…
Vinko Vrsalovic

14
@jww vim es una herramienta que se usa comúnmente para programadores, y las preguntas sobre las herramientas que se usan comúnmente para programadores se tratan en Stack Overflow . Aunque obviamente esto es más adecuado en Vi y Vim .
user202729

Respuestas:


2565

Usar en \rlugar de \n.

Sustituyendo por \ninserta un carácter nulo en el texto. Para obtener una nueva línea, use \r. Sin embargo, cuando busque una nueva línea, aún la usaría \n. Esta asimetría se debe al hecho de que \ny \r hacer cosas ligeramente diferentes :

\ncoincide con un final de línea (nueva línea), mientras que \rcoincide con un retorno de carro. Por otro lado, en las sustituciones \ninserta un carácter nulo mientras que \rinserta una nueva línea (más precisamente, se trata como la entrada <CR>). Aquí hay un pequeño ejemplo no interactivo para ilustrar esto, utilizando la función de línea de comando Vim (en otras palabras, puede copiar y pegar lo siguiente en un terminal para ejecutarlo). xxdmuestra un hexdump del archivo resultante.

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.

En otras palabras, \nha insertado el byte 0x00 en el texto; \rha insertado el byte 0x0a.


127
/ r se trata como presionar la tecla Enter / Return. Funciona en todas las plataformas.
Luka Marinko


14
Desearía que esto funcionara para vi clásico. En AIX v6.1, \rno funciona así. Pero puede presionar Ctrl-V Enteren lugar de escribir \r, y funciona.
eksortso

3
Llego tarde a la fiesta. Si \rinserta <CR>e \ninserta un valor nulo, ¿cómo reemplazaría algo con un retorno de carro?
Sr. Llama

2
@SunnyRaj, ¿estás seguro de la historia de CR y LF? Tenía la impresión de que originalmente LF movió el papel una fila hacia adelante pero no movió el cabezal de impresión, y CR movió el cabezal de impresión pero no movió el papel. Como resultado, si su sistema operativo no convirtió la entrada antes de imprimir, no podría usar solo LF ni CR para obtener la salida correcta. MS DOS usó datos sin formato de la impresora como formato de archivo de texto, Mac OS usó CR y lo convirtió al formato sin formato de la impresora y UNIX usó LF y lo convirtió al formato sin formato de la impresora.
Mikko Rantalainen

210

Aquí está el truco:

Primero, configure su sesión Vi (m) para permitir la coincidencia de patrones con caracteres especiales (es decir, nueva línea). Probablemente valga la pena poner esta línea en su archivo .vimrc o .exrc:

:set magic

A continuación, haz:

:s/,/,^M/g

Para obtener el ^Mpersonaje, escribe Ctrl+ Vy presiona Enter. Bajo Windows, hacer Ctrl+ Q, Enter. La única forma en que puedo recordar esto es recordando el poco sentido que tienen:

R: ¿Cuál sería el peor personaje de control para representar una nueva línea?

B: O q(porque generalmente significa "Salir") o vporque sería muy fácil escribir Ctrl+ Cpor error y matar al editor.

A: Hazlo así.


99
Estoy usando GVim en Windows, y no necesito ni el :set magic(tampoco está en mi ~ / _vimrc) ni ctrl-q. Solo un simple ctrl-vseguido de enter crea el ^Mpersonaje para mí muy bien.
Chris Phillips

55
Cv no representa una nueva línea; es el comando "escapar del siguiente carácter literal". No sé para qué Cv es un mnemotécnico, pero hay una razón por la que no se asigna mentalmente a la nueva línea.
Jim Stewart

27
Ctrl-v es un mnemotécnico para "textualmente", es decir, escapar de la siguiente tecla presionada a su código / carácter "textual". En Windows es pegar: para mantener las cosas familiares. Ctrl-Q es para "(un) Quote" quizás. Muy estúpido, de todos modos, pero puede usarlo en archivos binarios, por ejemplo, para buscar Ctrl-A a través de Ctrl-Z (Ascii 1-26, supongo).
Tomasz Gandor

1
Ctrl-Cen realidad no mata al editor, aunque puede cancelar su regreso al modo Normal. Ctrl-Vsignifica textualmente y Ctrl-Qsignifica que alguien cometió el error de cargar el $VIMRUNTIME/mswin.vimarchivo de configuración. No necesitas mswin. Simplemente use su propio vimrc en su lugar.
00dani

Wow esto es increíble. Solía ​​hacerlo sed -n l hasta ahora. Es bueno saber que se puede lograr lo mismo con Ctrl-vin vim.
Arpit

98

En la sintaxis s/foo/bar, \ry \ntienen diferentes significados, dependiendo del contexto.


Corto:

Para foo:

\ n = nueva línea (LF en Linux / Mac, CR + LF en Windows)
\ r = retorno de carro (CR)

Para bar:

\ r = es nueva línea
\ n = byte nulo.

Más largo (con números ASCII):

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

Aquí hay una lista de los caracteres de control ASCII . Insértelos en Vim a través de Ctrl+ V, Ctrl+ ---key---.

En Bash u otros shells de Unix / Linux, simplemente escriba Ctrl+ ---key---.

Prueba Ctrl+ Men Bash. Es lo mismo que golpear Enter, ya que el shell se da cuenta de lo que significa, a pesar de que los sistemas Linux usan avances de línea para delimitar la línea.

Para insertar literales en bash, anteponerlos con Ctrl+ Vtambién funcionará.

Probar en Bash:

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

Esto usa secuencias de escape ANSI . Inserte los dos ^['S a través Ctrl+ V, Esc.

También puede intentar Ctrl+ V, Ctrl+ M, Enterque será administrado por:

bash: $'\r': command not found

¿Recuerdas lo \rde arriba? :>

Esta lista de caracteres de control ASCII es diferente de una tabla de símbolos ASCII completa , ya que los caracteres de control, que se insertan en una consola / pseudoterminal / Vim a través de la Ctrltecla (jaja), se pueden encontrar allí.

Mientras que en C y en la mayoría de los otros lenguajes, usualmente usas los códigos octales para representar estos 'caracteres'.

Si realmente quieres saber de dónde viene todo esto: el TTY desmitificado . Este es el mejor enlace que encontrará sobre este tema, pero tenga cuidado: habrá dragones.


TL; DR

Usualmente foo= \n, y bar= \r.


1
Así que estoy intrigado de cómo sustituirías a un personaje con un retorno de carro
codehot

2
@codeshot :s/x/^M/gdebería hacer. Inserte la ^Mvía ctrl-vseguida de ctrl-m.
sjas

3
Gracias sjas, sabes que esta pregunta es una de las más raras de todos los tiempos. 1008 votos por la respuesta que básicamente no dice nada más que "vim hace lo que encontraste. Eso es porque vim hace lo que encontraste. Nunca olvides que vim hace lo que encontraste". Tenía la esperanza de encontrar una lista corta de códigos para personajes interesantes en el patrón, el reemplazo y la razón de la rareza, por lo que es fácil de recordar y predecir otras rarezas similares. Eso habría obtenido mi voto.
código

@codeshot, una lista de caracteres de control ASCII podría ayudarlo. Consulte cs.tut.fi/~jkorpela/chars/c0.html para obtener más información. Actualizaré mi respuesta para incluir dos enlaces.
sjas

55

Necesitas usar:

:%s/,/^M/g

Para obtener el ^Mpersonaje, presione Ctrl+ vseguido de Enter.


44
Tengo que hacer <Cv> <Cm> para obtener el carácter ^ M.
Jezen Thomas


24

Con Vim en Windows, use Ctrl+ Qen lugar de Ctrl+ V.


16

Esta es la mejor respuesta para mi forma de pensar, pero hubiera sido mejor en una tabla:

¿Por qué es \ ra nueva línea para Vim?

Entonces, reformulación:

Debe usar \rpara usar un avance de línea (ASCII 0x0A, la nueva línea de Unix) en un reemplazo de expresiones regulares, pero eso es peculiar del reemplazo; normalmente debe seguir esperando usarlo \npara el avance de línea y el \rretorno de carro.

Esto se debe a que Vim se usó \nen un reemplazo para referirse al carácter NIL (ASCII 0x00). Es posible que haya esperado que NIL haya estado en su \0lugar, liberando \npara su uso habitual para el avance de línea, pero \0ya tiene un significado en los reemplazos de expresiones regulares, por lo que se cambió a \n. Por lo tanto, ir más allá para cambiar también la nueva línea de \na \r(que en un patrón regex es el carácter de retorno de carro, ASCII 0x0D).

Personaje | Código ASCII | Representación C | Partido Regex | Reemplazo de expresiones regulares
------------------------- + ------------ + ----------- ------- + ------------- + ------------------------
nulo | 0x00 | \ 0 | \ 0 | \norte
avance de línea (nueva línea Unix) | 0x0a | \ n | \ n | \ r
retorno de carro | 0x0d | \ r | \ r | <desconocido>

NB: ^M( Ctrl+ V Ctrl+ Men Linux) inserta una nueva línea cuando se usa en un reemplazo de expresiones regulares en lugar de un retorno de carro como otros han aconsejado (solo lo intenté).

También tenga en cuenta que Vim traducirá el carácter de avance de línea cuando lo guarde en un archivo según su configuración de formato de archivo y eso podría confundir las cosas.


11

Desde Eclipse , los ^Mcaracteres se pueden incrustar en una línea y desea convertirlos en nuevas líneas.

:s/\r/\r/g

8

Pero si uno tiene que sustituir, entonces lo siguiente funciona:

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

En lo anterior, cada línea siguiente se sustituye por la línea siguiente, y luego |-y nuevamente una nueva línea. Esto se usa en tablas wiki.

Si el texto es el siguiente:

line1
line2
line3

Se cambia a

line1
|-
line2
|-
line3

7

Si necesita hacerlo para un archivo completo, también me sugirió que lo intentara desde la línea de comandos:

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

1
Tenga en cuenta que esto requiere GNU sed. Intente printf 'foo\\nbar\n' | sed 's/\\n/\n/g'ver si funcionará en su sistema. (Gracias a la buena gente de #bash en freenode por esta sugerencia).
Evan Donovan

Sí, pero la pregunta era sobre Vim. Hay una pregunta de desbordamiento de pila ¿ Cómo puedo reemplazar una nueva línea (\ n) usando sed? .
Peter Mortensen

5

Aquí está la respuesta que me funcionó. De este chico:

---- citando Use el editor vi para insertar un carácter de nueva línea en reemplazar


Algo más que tengo que hacer y no puedo recordar y luego tengo que mirar hacia arriba.

En vi, para insertar un carácter de nueva línea en una búsqueda y reemplazar, haga lo siguiente:

:%s/look_for/replace_with^M/g

El comando anterior reemplazaría todas las instancias de "look_for" con "replace_with \ n" (con \ n significa nueva línea).

Para obtener la "^ M", ingrese la combinación de teclas Ctrl+ V, y luego (suelte todas las teclas) presione la Entertecla.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.