Tengo un archivo de texto como este (usando gVim en Windows)
foo bar baz quux corge grault garply waldo fred plugh [...150 more lines...] xyzzy thud
Quiero agregar un número a cada línea del archivo. No use :set number
, pero agregue el número como texto antes de cada línea, de la siguiente manera, para que el número sea parte del archivo.
1. foo bar baz quux 2. corge grault garply 3. waldo fred plugh [...~150 more lines...] 155. xyzzy thud
Comentarios
Responder
Al estilo Vim puro:
:%s/^/\=line(".").". "
Explicación:
:%s/^/ " the substitution will be applied to the beginning of every line \= " the rest of the replacement part is an expression line(".").". " " the expression returns the current line number concatenated with a dot and a space
Consulte :help \=
y :help line()
.
Usar una expresión en la parte de reemplazo es muy poderoso y FWIW es un buen punto de entrada a vimscript.
Comentarios
- ¿Cómo puedo agregar este comando muy útil a un mapa de teclas en vimrc?
- Para acceder al tema de ayuda de vim para la sustitución:
:help sub-replace-expression
Respuesta
Una cosa buena acerca de las macros de Vim es que pueden recurrir (pueden invocarse a sí mismas ):
- Limpiar el registro q:
qqq
- Agregue el número a la primera línea:
ggI1.
(¡no olvide el espacio!) - Vuelva al inicio de la línea y comience a grabar una macro:
0qq
- Copie el número:
- Desplácese hacia abajo en una línea y pegue el número:
+P
- Regrese al inicio de la línea e incremente el número:
0<c-a>
- Vuelva al inicio de la línea (para que la macro no se rompa cuando llegue a cifras dobles):
0
- Llame a la macro una vez, para que sea recursiva. En este punto, todavía no hay nada en el registro q, por lo que no sucederá nada:
@q
. - Guarde la macro:
q
- Llame a la macro una vez más y observe las chispas volar:
@@
La macro luego continúe invocándose hasta que llegue al final del archivo.
Puede usar el truco de la macro recursiva para muchos otros problemas similares, por lo que es bueno tenerlo en cuenta.
Si no desea utilizar una macro recursiva por algún motivo, puede omitir los pasos 1 y 8 y utilizar un recuento para ejecutar la macro varias veces, por ejemplo 100@q
ejecutará la macro q
100 veces.
Comentarios
- Cosas poderosas, me inclino ante tu maestría. Las macros son como magia negra para mí …
- @ropata, una macro es solo una secuencia de (en su mayoría) comandos de modo normal.
- @romainl Creo que ‘ como una secuencia de pulsaciones de teclas .
- @Rich, puede ser una secuencia de muchas cosas, incluidos los comandos ex.
- @romainl Sí, esa ‘ es la razón por la que creo que ‘ es mejor pensar en ello como pulsaciones de teclas. Reproduce exactamente lo que escribe en el teclado (incluidos, como dice, los comandos ex), como si lo hubiera escrito todo manualmente.
Responder
Me gusta usar el comando global vim para realizar tareas como esta. Esto se aplica a agregar iteración al comienzo de una línea o modificar un símbolo en el texto. Parece más complicado que las otras soluciones, pero es un patrón bastante flexible para usar cuando lo tiene a mano, y es fácil de modificar sin pensarlo mucho.
Primero, elija su rango (qué líneas quiere aplicar esto). Normalmente uso marcas (p. Ej.ma
en la primera línea y mb
en la segunda, pero también puede usar números de línea o selección visual), luego ingrese una modificación de el siguiente comando (actualmente ajustado para su caso de uso)
:let i=1|"a,"bg/^/s/^/\=i.". "/|let i=i+1
Deconstrucción
:let i=1
Esto configura la variable i
con un valor inicial. Por lo general, las listas comienzan con 1, por lo que «estoy configurando i en 1.
|
La barra inicia un nuevo comando
"a,"b
Esto establece el rango del siguiente comando. Voy de la marca a
a la marca b
, que se establecería en la primera y última línea de su lista.
g/^/
Este es el comando global. Busca en el archivo (o rango) una expresión regular determinada y ejecutará el resto de la línea de comando en cada de las líneas que coincidan. Estoy haciendo coincidir todas las líneas buscando «comienzo de línea». Si tuviera un texto como
Item some txt other text Item second item whatever Item third
y solo quiero poner estas etiquetas delante de Item
e ignore las otras líneas, haga g/Item/
o g/^Item/
en su lugar (asumiendo el texto literal del elemento )
s/^/\=i.". "/
Esto ejecuta la expresión regular para reemplazar el comienzo de la línea con el valor de i
concatenado con a .
. Generalmente, puede hacer esto con cualquier cosa (reemplace la etiqueta Item
con el número, por ejemplo).
|let i=i+1
Aunque la barra inicia un nuevo comando, configura un segundo comando para que se ejecute dentro del comando global, en lugar de después de que el global esté completo. El resultado es que incrementamos i
antes de que g procese la siguiente línea. Aquí hay otro lugar de flexibilidad. La modificación de i puede ser cualquier cosa (incre por 2, llame a una función que genere el siguiente elemento de la secuencia de Fibonacci, lo que sea).
Responder
Agregar números a todas las líneas
Es posible utilizar :%!nl -ba
o :%!cat -n
comandos que agregarán números de línea a todas las líneas.
En Windows, «Debemos tener Cygwin / MSYS / SUA instalado.
Agregar números a las líneas seleccionadas
Para agregar números solo para las líneas seleccionadas, selecciónelos en modo visual ( v y cursores), luego, cuando termine, ejecute el comando: :%!nl
(ignore las líneas en blanco) o :%!cat -n
(líneas en blanco incluidas).
Formateo
Para eliminar espacios adicionales, selecciónelos en el bloque visual ( Ctrl + v ) y elimínelos ( x ).
Para agregar algunos caracteres (.
, :
, ) después de los números, selecciónelos en el bloque visual ( Ctrl + v ), luego agregue el carácter ( A , escriba el carácter, luego termine con Esc ).
Comentarios
- Esto no da el mismo formato que el dado en la pregunta. Sin embargo, me gusta la simplicidad de la solución.
- @KarlYngveLerv å g Gracias, incluido eso en la respuesta.
Respuesta
Una modificación de la respuesta de romainl :
:%s/^\(\d\+\. \)\?/\=line(".").". "
Esto no solo agregar números de línea, también reemplazará los números de línea existentes si ya están allí. De, si ha insertado una línea a mitad de camino, volverá a numerar todo como se esperaba.
Esto funciona reemplazando cualquier número seguido de a. Y un espacio al comienzo de la línea con un nuevo número . Obviamente, esto se romperá si tiene una línea que ya comienza con este patrón, así que úselo con pensamiento.
La parte agregada:
-
^
– Inicio de línea -
\(
– Iniciar nuevo subgrupo -
\d\+
– Coincide con un dígito una o más -
\.
– Coincide con un punto (
.
) y un espacio.
-
\)
– Fin del subgrupo -
\?
– Haga que el grupo sea opcional, para que funcione como antes si todavía no hay ningún número en esta línea.
Sugerencia adicional :
Para eliminar los números de línea, puede usar el mismo patrón con la parte de reparación vacía:
:%s/^\(\d\+\. \)\?//
Responder
I1. <esc>^qqyWjP^<C-a>q
Esto numera las dos primeras líneas y puede presionar @q
para numerar las líneas siguientes (o escriba ex. 18@q
si desea tener un total de 20 líneas).
Explicación:
I1. <esc> Number the first line hqq Go back to the start of the line and start recording a macro yWjP Copy the line number to the next line ^<C-a> Increment the next line"s line number q Finish recording
El beneficio de esto es que no requiere ningún comando externo, lo cual es útil si » trabajando con Vim en Windows, por ejemplo.
Comentarios
- Después de escribir
1. <esc>h
estás en el segunda columna, no primera columna. Reemplazaríah
con0
, después de lo cual creo que su solución debería ser muy buena. - @KarlYngveLerv å g Vaya, fue un error tipográfico. Gracias, arregló.
- No hay problema. Sin embargo, aún no ha actualizado la explicación. Además: en muchos teclados,
^
espera un segundo carácter para permitir combinaciones de escritura como^a -> â
. Todavía estoy de acuerdo en que es la mejor solución, pero creo que esto también debería mencionarse.
Responder
I Creo que la respuesta elegida es la mejor, pero en el espíritu de variedad, ofreceré una alternativa usando un programa externo:
:%!cat -n
Esto filtrará todo su búfer (indicado por %
) a través del programa externo, cat
, donde -n
La bandera antepone a cada línea de entrada un número de línea.
Esto, por supuesto, requiere que tenga cat
instalado, lo cual es cierto para (probablemente) todos los sistemas Unix -como sistemas.
Consulte :help :range!
para obtener más detalles sobre el filtrado a través de programas externos.
Comentarios
- Me doy cuenta de que el autor de la pregunta está usando gVim en Windows, por lo que esta solución probablemente no ‘ funcionará allí. Sin embargo, creo que todavía brinda una oportunidad para otros t para aprender de él.
- Si ‘ instaló
msysgit
y lo agregó a su PATH (IIRC it ‘ es una opción de instalación), esta solución también debería funcionar en Windows. -
cat -n
no es POSIX, peronl
sí lo es, por lo que podría ser un mejor opción.
Respuesta
Una solución un poco pirateada podría ser la siguiente (todo lo escrito entre < y> deben insertarse después de presionar Ctrl + v ):
:%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd
Deconstrucción
:%normal {commands}
ejecuta el comando en modo normal en cada línea especificada por el rango, en este caso cada línea
:redir @"
redirige cada salida realizada por comandos ex al búfer sin nombre.
:.=
es un comando ex que genera la línea actual número (con una nueva línea anterior, lamentablemente)
:redir END
deja de redireccionar al búfer sin nombre
I<C-R>".<Tab><Esc>
inserta el contenido del búfer sin nombre con un. y una pestaña al frente de cada línea y sale del modo de inserción.
kdd
sube una línea y elimina la nueva línea que es el resultado de:. = comando.
awk
es probablemente la herramienta para este trabajo. Pero yo ‘ m en Windows (suspiro).cat
onl
, que pueden hacer líneas numéricas, pero no son ‘ t generalmente disponible en Windows (como OP indica en su comentario sobreawk
). Las dos mejores soluciones son Vim puro. Por último, todas las líneas frente a un párrafo es solo una cuestión de selección de rango. Claramente no es un gran problema.