vi en Linux — práctica con un ifcfg de verdad: activar la tarjeta, limpiar el archivo y mudarlo de red (sin tocar el ratón)
La segunda semana de redes ya sabía salir de vi, pero tardaba cinco minutos en cada cambio: flecha, flecha, flecha, borrar letra a letra, escribir… Un compañero me vio y me dijo: «¿por qué no haces cw?». Cambié una palabra entera con dos teclas y me di cuenta de que había estado usando vi como si fuera el bloc de notas. La lección: en vi no se edita letra a letra, se edita con órdenes que dicen qué cambiar y hasta dónde.
Esta práctica aplica lo de la teoría de vi a tres situaciones del laboratorio, todas sobre el archivo de configuración de una tarjeta de red, ifcfg-enp2s0: dejarlo listo para que la tarjeta arranque sola, limpiar un archivo lleno de restos y mudar la estación a otra red. Los tres son de nivel medio y usan archivos parecidos a los de verdad: con líneas repetidas, comentarios viejos y valores que hay que cambiar en varios sitios a la vez.
Tabla de Contenidos
Antes de empezar
Conviene tener claro:
- Los tres modos y que Esc te devuelve siempre al normal.
- Los movimientos básicos (
j,$,G,5G,/texto,n). - La gramática operador + movimiento (
dd,3dd,cw,yy,p). - La diferencia entre
:wqy:q!.
Si alguno te suena dudoso, repasa la teoría antes de seguir.
En este artículo, «el código» de cada programa son las teclas que pulsas dentro de vi, con un comentario que explica el porqué. <Esc> es Escape y <CR> es Enter. Practica siempre sobre una copia (cp ifcfg-enp2s0 prueba): así un error no te deja sin red.
Programa 1: activar la tarjeta al arrancar
La estación del laboratorio tiene este ifcfg-enp2s0. Tiene dos problemas: BOOTPROTO=dhcp (pide la IP a un servidor DHCP, pero en el lab la IP se pone a mano) y ONBOOT=no (la tarjeta no se activa al arrancar). Además falta la línea NETWORK con la dirección de la red.
$ cat -n ifcfg-enp2s0
1 DEVICE=enp2s0
2 BOOTPROTO=dhcp
3 ONBOOT=no
4 IPADDR=192.168.2.27
5 NETMASK=255.255.255.0
6 GATEWAY=192.168.2.1
La idea
Tres cambios, cada uno con la herramienta justa:
- Saltar a
dhcpcon una búsqueda y cambiar la palabra entera concw. - Saltar al
=nocon otra búsqueda, avanzar un carácter y cambiarnoporyes. - Ir a la última línea y abrir una nueva debajo con
o.
Nada de flechas: las búsquedas te dejan el cursor exactamente donde quieres, aunque el archivo tenga cien líneas.
Antes de programar, piensa en dónde caerá el cursor. /=no deja el cursor sobre el =, no sobre la n: por eso hace falta la l antes del cw.
El código
/dhcp<CR> # el cursor salta a la d de dhcp cwnone<Esc> # dirección fija: sin DHCP /=no<CR> # el cursor cae en el = de ONBOOT=no lcwyes<Esc> # un paso a la derecha y cambia no por yes GoNETWORK=192.168.2.0<Esc> # abre una línea al final y escribe la red :wq<CR> # guarda y sale
Fíjate en el zoom de la parte más delicada, la segunda búsqueda:
/=no<CR> # el cursor cae en el = de ONBOOT=no lcwyes<Esc> # un paso a la derecha y cambia no por yes
¿Por qué buscar =no y no no? Porque no aparece también dentro de none, que acabamos de escribir en la línea 2. Buscando =no el patrón solo encaja en la línea 3. Y la l es necesaria porque cw cambia desde el cursor hasta el final de la palabra: si lo hiciéramos sobre el =, borraríamos el = (que para vi es una palabra en sí mismo).
Salida
Justo antes del :wq, la pantalla de vi:
DEVICE=enp2s0
BOOTPROTO=none
ONBOOT=yes
IPADDR=192.168.2.27
NETMASK=255.255.255.0
GATEWAY=192.168.2.1
NETWORK=192.168.2.0
~
~
7,19 All
Y el archivo en el disco después de guardar:
$ cat -n ifcfg-enp2s0
1 DEVICE=enp2s0
2 BOOTPROTO=none
3 ONBOOT=yes
4 IPADDR=192.168.2.27
5 NETMASK=255.255.255.0
6 GATEWAY=192.168.2.1
7 NETWORK=192.168.2.0
Comprobación: había 6 líneas y o añadió una, 6 + 1 = 7. La posición 7,19 es la última letra de NETWORK=192.168.2.0 (19 caracteres). Las líneas 1, 4, 5 y 6 no se han tocado. En el dibujo se ve cada cambio con la orden que lo hizo:
Preguntas que te puedes hacer
¿Por qué cw y no x cuatro veces? Porque cw borra la palabra entera y te deja en inserción en un solo paso. Con x tendrías que contar letras (dhcp tiene 4, pero bootp tendría 5) y luego pulsar i.
¿Y si el archivo tuviera dos dhcp? /dhcp va a la primera. Tras cambiarla, n salta a la siguiente y . repite el último cambio (cwnone) sin volver a escribirlo.
¿Por qué G y luego o, y no o directamente? o abre la línea debajo de donde esté el cursor. Tras el segundo cw estábamos en la línea 3; sin G, NETWORK habría quedado entre ONBOOT e IPADDR. Al archivo le daría igual (el orden no importa en un ifcfg), pero queremos que quede ordenado.
¿Hace falta :wq o vale con :x? Valen los dos (y ZZ). La diferencia es que :x solo escribe si hay cambios: no toca la fecha de modificación si no has cambiado nada.
Buscar /no en lugar de /=no. Después de cambiar dhcp por none, la primera coincidencia de no está dentro de none y el cw destrozaría la línea 2.
Pruébalo tú
- Sobre el archivo original, haz los dos primeros cambios con
:%sen lugar de con búsquedas (pista: necesitas dos sustituciones). - Añade la línea
DNS1=193.145.147.22encima deGATEWAYusandoO.
Programa 2: limpiar un archivo lleno de restos
Este ifcfg-enp2s0 lo han tocado tres personas: hay un IPADDR repetido, tres líneas comentadas con la configuración vieja y GATEWAY y NETMASK en el orden contrario al resto de archivos del aula. Y falta NETWORK.
$ cat -n ifcfg-enp2s0
1 DEVICE=enp2s0
2 BOOTPROTO=none
3 ONBOOT=yes
4 IPADDR=10.0.1.27
5 IPADDR=10.0.1.27
6 #IPADDR=192.168.2.27
7 #GATEWAY=192.168.2.1
8 #NETMASK=255.255.255.0
9 GATEWAY=10.0.1.1
10 NETMASK=255.255.255.0
La idea
Borrar con número para no repetir órdenes, y mover líneas cortando y pegando:
5G+ddquita elIPADDRrepetido (línea 5).- Las tres líneas comentadas quedan seguidas en la 5, 6 y 7: un solo
3dd. ddpintercambia dos líneas: corta la del cursor y la pega debajo de la siguiente.G+oañade la línea que falta.
Antes de programar, piensa en cómo se renumeran las líneas. Después del primer dd, el comentario que estaba en la línea 6 pasa a ser la 5. Por eso el 3dd va justo después, sin moverse.
El código
5G # la línea 5: el IPADDR repetido dd # fuera 3dd # las tres líneas viejas comentadas ddp # GATEWAY baja debajo de NETMASK GoNETWORK=10.0.1.0<Esc> # la línea que faltaba :wq<CR>
El truco del programa es ddp. Veámoslo con zoom:
ddp # GATEWAY baja debajo de NETMASK
dd borra la línea GATEWAY y la guarda en el portapapeles de vi; al borrarla, NETMASK sube y el cursor queda sobre ella. p pega lo guardado debajo del cursor. Resultado: las dos líneas han cambiado de sitio. Son tres teclas que acabarás usando sin pensar.
Salida
Tras 5G y dd:
DEVICE=enp2s0
BOOTPROTO=none
ONBOOT=yes
IPADDR=10.0.1.27
#IPADDR=192.168.2.27
#GATEWAY=192.168.2.1
#NETMASK=255.255.255.0
GATEWAY=10.0.1.1
NETMASK=255.255.255.0
5,1 All
De 10 líneas a 9, y el cursor sigue en la línea 5, que ahora es el primer comentario. Tras 3dd:
DEVICE=enp2s0 BOOTPROTO=none ONBOOT=yes IPADDR=10.0.1.27 GATEWAY=10.0.1.1 NETMASK=255.255.255.0 ~ ~ ~ 3 fewer lines 5,1 All
3 fewer lines: 9 − 3 = 6. Tras ddp y la línea nueva:
DEVICE=enp2s0
BOOTPROTO=none
ONBOOT=yes
IPADDR=10.0.1.27
NETMASK=255.255.255.0
GATEWAY=10.0.1.1
NETWORK=10.0.1.0
~
~
7,16 All
El archivo final en el disco:
$ cat -n ifcfg-enp2s0
1 DEVICE=enp2s0
2 BOOTPROTO=none
3 ONBOOT=yes
4 IPADDR=10.0.1.27
5 NETMASK=255.255.255.0
6 GATEWAY=10.0.1.1
7 NETWORK=10.0.1.0
Esta es la traza de las líneas que hay tras cada orden:
| Paso | Orden | Líneas | Cursor | Qué pasó |
|---|---|---|---|---|
| 0 | (abrir) | 10 | 1 | archivo original |
| 1 | 5G dd | 9 | 5 | fuera el IPADDR repetido |
| 2 | 3dd | 6 | 5 | fuera los tres comentarios (6, 7 y 8 originales) |
| 3 | ddp | 6 | 6 | GATEWAY y NETMASK intercambiadas |
| 4 | G o… | 7 | 7 | NETWORK añadida al final |
Y las tres fases dibujadas:
Preguntas que te puedes hacer
¿Por qué no :g/^#/d para borrar los comentarios? Funcionaría (borra todas las líneas que empiezan por #) y es más potente, pero 3dd te enseña a contar líneas, que es lo que necesitas el 90 % de las veces. Tienes :g en el chuletario de los ejercicios.
¿Y si cuento mal y hago 4dd? Te llevas también GATEWAY. Pulsa u y vuelven las cuatro, porque 4dd es un único cambio.
¿ddp funciona en la última línea? No del todo: si borras la última línea, el cursor sube a la anterior y p la pega debajo… justo donde estaba. Para subir una línea se usa ddkP.
¿Dónde fue el IPADDR borrado? Al portapapeles de vi. Si justo después pulsaras p, volvería. Cada d sustituye lo que había guardado, igual que un «cortar».
Hacer el 3dd en la línea 6 «porque los comentarios empezaban en la 6». Después del primer dd todo ha subido una posición: estarías borrando dos comentarios y GATEWAY.
Pruébalo tú
- Repite la limpieza en otro orden: primero
3dden los comentarios y después eldddel repetido. ¿Qué número de línea tienes que usar ahora? - Copia la línea
NETMASKconyyy pégala al final conG+p. Después bórrala condd.
Programa 3: mudar la estación a otra red
El aula se reorganiza y la estación pasa de la red 10.0.1.x a la 10.0.5.x. Hay que cambiar la IP, la puerta de enlace y la dirección de red, sin tocar la máscara ni nada más:
$ cat -n ifcfg-enp2s0
1 DEVICE=enp2s0
2 BOOTPROTO=none
3 ONBOOT=yes
4 IPADDR=10.0.1.27
5 NETMASK=255.255.255.0
6 GATEWAY=10.0.1.1
7 NETWORK=10.0.1.0
La idea
Primero localizar qué líneas llevan la red vieja (para saber qué esperar) y después cambiarlas todas de una vez con :%s, cuidando dos cosas: que los puntos sean puntos de verdad y que el patrón termine en punto, para no tocar números que solo empiecen igual.
Antes de programar, piensa en cuántas sustituciones deberían salir. Si vi te dice otro número, el patrón está mal.
El código
/GATEWAY<CR> # comprueba dónde está la puerta de enlace /10<CR> # busca 10 desde ahí n # siguiente n # y otra vez (vuelve arriba) :%s/10\.0\.1\./10.0.5./g<CR> :w<CR> # guarda sin salir :q<CR>
La línea importante, desmontada:
:%s/10\.0\.1\./10.0.5./g
% para todas las líneas, \. para que el punto sea un punto (sin la barra, . encaja con cualquier carácter) y el punto final del patrón hace que solo cambie 10.0.1. seguido de algo, nunca un 10.0.10 o un 10.0.15. La g cambia todas las apariciones de cada línea (aquí hay una por línea, pero es buena costumbre).
Salida
Las búsquedas dejaron este rastro en la regla de vim:
| Teclas | Posición | Carácter | Qué encontró |
|---|---|---|---|
/GATEWAY Enter | 6,1 | G | la línea de la puerta de enlace |
/10 Enter | 6,9 | 1 | 10.0.1.1, justo detrás de GATEWAY= (8 caracteres) |
n | 7,9 | 1 | 10.0.1.0, detrás de NETWORK= |
n | 4,8 | 1 | dio la vuelta: 10.0.1.27, detrás de IPADDR= (7) |
Tres líneas con la red vieja: 4, 6 y 7. Tras la sustitución:
DEVICE=enp2s0 BOOTPROTO=none ONBOOT=yes IPADDR=10.0.5.27 NETMASK=255.255.255.0 GATEWAY=10.0.5.1 NETWORK=10.0.5.0 ~ ~ 3 substitutions on 3 lines 7,1 All
3 substitutions on 3 lines: el número que esperábamos. :w guarda sin salir y vim lo confirma:
DEVICE=enp2s0 BOOTPROTO=none ONBOOT=yes IPADDR=10.0.5.27 NETMASK=255.255.255.0 GATEWAY=10.0.5.1 NETWORK=10.0.5.0 ~ ~ "ifcfg-enp2s0" 7L, 113B written 7,1 All
7L, 113B written: 7 líneas y 113 bytes. El archivo original tenía los mismos bytes, porque cambiamos un 1 por un 5 en tres sitios (mismo tamaño). En el disco:
$ cat -n ifcfg-enp2s0
1 DEVICE=enp2s0
2 BOOTPROTO=none
3 ONBOOT=yes
4 IPADDR=10.0.5.27
5 NETMASK=255.255.255.0
6 GATEWAY=10.0.5.1
7 NETWORK=10.0.5.0
El dibujo trocea la orden y enseña las tres líneas que cambió.
Preguntas que te puedes hacer
¿Qué pasaría sin el punto final del patrón? Con :%s/10\.0\.1/10.0.5/g aquí saldría lo mismo, pero en una red con IPADDR=10.0.1.15 y GATEWAY=10.0.10.1 también cambiarías 10.0.10.1 por 10.0.50.1. El punto final es un seguro barato.
¿Por qué buscar antes si :%s ya lo hace todo? Para saber qué número esperar. Contrastar «3 líneas encontradas» con «3 substitutions» es la forma rápida de comprobar que el patrón hace lo que crees.
¿Puedo ver los cambios uno a uno? Sí: con la bandera c (:%s/…/…/gc) vim te pregunta en cada uno replace with 10.0.5. (y/n/a/q/l/^E/^Y)?.
¿Y si me equivoco de red? u deshace la sustitución entera (es un solo cambio), aunque haya tocado tres líneas.
Escribir :s sin %. Solo mira la línea del cursor (aquí, la 4 tras la última búsqueda) y cambiarías la IP pero no la puerta de enlace ni la red. La estación quedaría en una red y su gateway en otra.
Pruébalo tú
- Cambia solo las líneas 4 a 6 con un rango (
:4,6s/…) y comprueba concat -nqueNETWORKsigue igual. - Usa la bandera
cpara aceptar el cambio deIPADDRy rechazar el deGATEWAY.
Errores típicos en esta práctica
- Teclear con el cursor en el sitio equivocado:
cwyddactúan desde el cursor. Una búsqueda (/texto) antes de cada cambio evita sorpresas. - Contar líneas sin tener en cuenta los borrados anteriores: después de un
dd, todo lo de debajo sube una posición. - Buscar un texto que también aparece en otro sitio:
/noencuentranone. Haz el patrón más concreto (/=no). - Olvidar escapar el punto en
:s:.es «cualquier carácter»; para un punto,\.. - Sustituir sin
%: solo cambia la línea del cursor. - Probar sobre el archivo real: trabaja sobre una copia hasta que la secuencia salga bien.
Pruébalo en tu terminal
vi también se puede usar sin abrir la pantalla: vim -es (modo ex silencioso) ejecuta órdenes de las que escribirías tras los dos puntos y termina. Es ideal dentro de un script. Esta es la misma mudanza del programa 3, ejecutada de verdad desde la terminal:
# vi sin abrir la pantalla: ex en modo silencioso (-es) ejecuta las órdenes de : y termina cat -n ifcfg-enp2s0 vim -u NONE -es -c '%s/10\.0\.1\./10.0.5./g' -c 'wq' ifcfg-enp2s0 # la misma sustitución del programa 3 echo $? # 0 = todo fue bien cat -n ifcfg-enp2s0
La sesión real:
$ cat -n ifcfg-enp2s0
1 DEVICE=enp2s0
2 BOOTPROTO=none
3 ONBOOT=yes
4 IPADDR=10.0.1.27
5 NETMASK=255.255.255.0
6 GATEWAY=10.0.1.1
7 NETWORK=10.0.1.0
$ vim -u NONE -es -c '%s/10\.0\.1\./10.0.5./g' -c 'wq' ifcfg-enp2s0
$ echo $?
0
$ cat -n ifcfg-enp2s0
1 DEVICE=enp2s0
2 BOOTPROTO=none
3 ONBOOT=yes
4 IPADDR=10.0.5.27
5 NETMASK=255.255.255.0
6 GATEWAY=10.0.5.1
7 NETWORK=10.0.5.0
Qué observar:
- Cada
-ces una orden de las de:(sin los dos puntos), y se ejecutan en orden: primero la sustitución, despuéswq. -u NONEarranca vim sin configuración, para que se comporte igual en cualquier máquina.- vim no escribe nada en la terminal: en modo silencioso solo habla si hay un error.
echo $?da 0: todo fue bien (en los ejercicios verás un caso en el que también da 0… y no hace lo que querías).- El resultado es idéntico al del programa 3: las líneas 4, 6 y 7 cambian y las demás no.
Resumen
- En vi se edita con órdenes, no letra a letra:
cwcambia una palabra,ddborra una línea,oabre una nueva. - Una búsqueda (
/texto) es la forma más rápida y segura de poner el cursor en su sitio; haz el patrón concreto (/=no). - Un número delante repite la orden (
3dd), y después de cada borrado las líneas se renumeran. ddpintercambia dos líneas;udeshace una orden entera aunque haya tocado varias líneas.:%s/patrón/reemplazo/gcambia todo el archivo; escapa los puntos (\.) y comprueba el número de sustituciones.vim -es -c 'orden' -c 'wq'aplica las mismas órdenes desde un script.
Checklist: ¿lo has practicado?
- ¿Has hecho los tres programas sobre una copia y comprobado el resultado con
cat -n? - ¿Has intentado los «Pruébalo tú» sin mirar la teoría?
- ¿Sabes por qué
/=noes mejor que/noen el programa 1? - ¿Puedes explicar por qué el
3dddel programa 2 va en la línea 5 y no en la 6? - ¿Sabes qué hace cada parte de
:%s/10\.0\.1\./10.0.5./g? - ¿Has probado
vim -esdesde la terminal?
Si has respondido que sí a casi todo, estás listo para los ejercicios de vi, donde ya no te doy las teclas hechas. ¡Nos vemos allí!
Siguiente paso: ejerciciosvi en Linux — ejercicios con resolv.conf, líneas repetidas y una tarjeta clonada (y el NBOOT=yes que nadie había escrito)¿Te ha servido este artículo? Así puedes apoyar SergioLearns →




El hardware que sostiene al sistema operativo — teoría con la práctica de IC2 en la impresora, una interrupción que lo para todo y una caché que acierta (y el bucle infinito que no colgó mi portátil)