Aprende-Vim/cap14_comandos_externos.md

222 lines
7.5 KiB
Markdown
Raw Normal View History

2021-01-18 23:53:50 +01:00
# Capítulo 14: Comandos externos
2020-09-08 22:33:03 +02:00
2021-01-18 23:53:50 +01:00
Dentro del sistema Unix, encontrarás muchos comandos pequeños y muy específicos donde cada uno hace una tarea y la hace eficientemente. Puedes encadenar estos comandos para que funcionen de manera conjunta para dar solución a un problema complejo. ¿No sería genial si pudieras utilizar estos comandos dentro de Vim?
2020-09-08 22:33:03 +02:00
2021-01-18 23:53:50 +01:00
En este capítulo, aprenderás cómo extender las funcionalidades de Vim para que trabaje sin problemas con estos comandos externos.
2020-09-08 22:33:03 +02:00
## El comando _bang_
2020-09-08 22:33:03 +02:00
Vim tiene un comando llamado _bang_ \(`!`\) que puede realizar tres cosas:
2020-09-08 22:33:03 +02:00
1. Leer la salida estándar \(STDOUT\) de un comando externo dentro del _buffer_ actual.
2. Escribir el contenido de tu _buffer_ como la entrada estándar \(STDIN\) a un comando externo.
2021-01-18 23:53:50 +01:00
3. Ejecutar un comando externo desde dentro de Vim.
2020-09-08 22:33:03 +02:00
## Leer la salida estándar \(STDOUT\) de un comando dentro de Vim
2020-09-08 22:33:03 +02:00
La sintaxis para leer la salida estándar \(STDOUT\) de un comando externo dentro del _buffer_ actual es:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:r !{cmd}
```
2021-01-18 23:53:50 +01:00
`:r` es el comando de Vim para leer. Si lo utilizas sin `!`, puedes utilizarlo para obtener el contenido de un archivo. Si tienes un archivo llamado `archivo1.txt` en el directorio actual y ejecutas:
2020-09-08 22:33:03 +02:00
```text
2021-01-18 23:53:50 +01:00
:r archivo1.txt
2020-09-08 22:33:03 +02:00
```
Vim pondrá el contenido de `archivo1.txt` dentro del _buffer_ actual.
2020-09-08 22:33:03 +02:00
Si ejecutas el comado `:r` seguido por un `!` y un comando externo, la salida de ese comando será insertada dentro del _buffer_ actual. Para obtener el resultado del comando `ls`, ejecuta:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:r !ls
```
2021-01-18 23:53:50 +01:00
Esto devolverá algo similar a esto:
2020-09-08 22:33:03 +02:00
```text
2021-01-18 23:53:50 +01:00
archivo1.txt
archivo2.txt
archivo3.txt
2020-09-08 22:33:03 +02:00
```
2021-01-18 23:53:50 +01:00
Puedes leer los datos desde el comando `curl`:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:r !curl -s 'https://jsonplaceholder.typicode.com/todos/1'
```
2021-01-18 23:53:50 +01:00
El comando `r` también acepta una dirección:
2020-09-08 22:33:03 +02:00
```text
2021-01-18 23:53:50 +01:00
:10r !cat archivo1.txt
2020-09-08 22:33:03 +02:00
```
Ahora la salida estándar \(STDOUT\) de ejecutar `cat archivo1.txt` será insertada después de la línea 10.
2020-09-08 22:33:03 +02:00
## Escribir el contenido de un _buffer_ en un comando externo
2020-09-08 22:33:03 +02:00
Además de para guardar un archivo, también puedes utilizar el comando de escribir \(`:w`\) para pasar el contenido del _buffer_ actual como la entrada estándar \(STDIN\) a un comando externo. La sintaxis es:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:w !cmd
```
Si tienes las siguientes expresiones en el _buffer_:
2020-09-08 22:33:03 +02:00
```text
2021-01-21 19:29:43 +01:00
console.log("Hola Vim");
console.log("Vim es asombroso");
2020-09-08 22:33:03 +02:00
```
2021-01-21 19:29:43 +01:00
Asegúrate de tener [node](https://nodejs.org/en/) instalado en tu equipo y después ejecuta:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:w !node
```
Vim usará `node` para ejecutar las expresiones de Javascript para mostrar por pantalla "Hola Vim" y "Vim is asombroso".
2020-09-08 22:33:03 +02:00
Al utilizar el comando `:w`, Vim utiliza todo el texto del _buffer_ actual, de manera similar al comando global \(la mayoría de comandos de la línea de comandos, si no les pasas un rango, solo ejecutan el comando en la línea actual, no en todo el _buffer_\). Si le pasas al comando `:w` una dirección específica:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:2w !node
```
2021-01-21 19:29:43 +01:00
Vim solo utilizará el texto de la segunda línea en el intérprete de `node`.
2020-09-08 22:33:03 +02:00
Existe una sutil pero significativa diferencia entre `:w !node` y `:w! node`. Con `:w !node`, estás "escribiendo" el texto del _buffer_ actual en un comando externo, en este caso `node`. Con `:w! node`, estás forzando a guardar un archivo y dándole el nombre de "node".
2020-09-08 22:33:03 +02:00
2021-01-21 19:50:56 +01:00
## Ejecutando un comando externo
2020-09-08 22:33:03 +02:00
Puedes ejecutar un comando externo desde dentro de Vim con comando _bang_. La sintaxis es:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:!cmd
```
2021-01-21 19:50:56 +01:00
Verás el contenido del directorio actual en su formado extendido, ejecuta:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:!ls -ls
```
2021-01-21 19:50:56 +01:00
Para matar un proceso que se está ejecutando con el identificativo de proceso PID 3456, puedes ejecutar:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:!kill -9 3456
```
2021-01-21 19:50:56 +01:00
Puedes ejecutar cualquier comando externo sin dejar Vim y así permanecer centrado en tu tarea.
2020-09-08 22:33:03 +02:00
2021-01-21 19:50:56 +01:00
## Filtranto textos
2020-09-08 22:33:03 +02:00
2021-01-21 19:50:56 +01:00
Si das un rango al comando `!`, esto puede ser utilizado para filtrar textos. Supongamos que tenemos estos textos:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
hello vim
hello vim
```
Vamos a convertir a mayúsculas la línea actual utilizando el comando `tr` \(translate\). Ejecuta:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:.!tr '[:lower:]' '[:upper:]'
```
2021-01-21 19:50:56 +01:00
Este es el resultado:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
HELLO VIM
hello vim
```
2021-01-21 19:50:56 +01:00
Vamos a ver en detalle el comando:
2020-09-08 22:33:03 +02:00
* `.!` ejecuta el filtro del comando en la línea actual.
* `!tr '[:lower:]' '[:upper:]'` llama al comando `tr` para reemplazar los caracteres en minúsculas a mayúsculas.
Es imperativo pasar un rango para ejecutar el comando externo como un filtro. Si tratas de ejecutar el comando anterios sin el `.` \(`:!tr '[:lower:]' '[:upper:]'`\), verás un error.
2020-09-08 22:33:03 +02:00
2021-01-21 19:50:56 +01:00
Asumamos ahora que necesitamos eliminar la segunda columna de ambas líneas utilizando el comando `awk`:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:%!awk "{print $1}"
```
2021-01-21 19:50:56 +01:00
Este es el resultado:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
hello
hello
```
2021-01-21 19:50:56 +01:00
La explicación:
* `:%!` ejecuta el filtro del comando en todas las líneas \(`%`\).
* `awk "{print $1}"` imprime solo la primera columna. En este caso la palabra "hello".
2020-09-08 22:33:03 +02:00
2021-01-21 19:50:56 +01:00
Puedes encadenar múltiples comando con el operado `|` de igual manera que en la terminal. Supongamos que tenemos un archivo con estos elementos de un delicioso desayuno:
2020-09-08 22:33:03 +02:00
```text
2021-01-21 19:50:56 +01:00
nombre precio
Tarde chocolate 10
Tarta merengue 9
Tarta frambuesa 12
2020-09-08 22:33:03 +02:00
```
2021-01-21 19:50:56 +01:00
Si necesitas ordenar la lisya en base al precio y mostrar solo el menu incluso con los espacios, puedes ejecutar:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
:%!awk 'NR > 1' | sort -nk 3 | column -t
```
2021-01-21 19:50:56 +01:00
El resultado:
```text
2021-01-21 19:50:56 +01:00
Tarta merengue 9
Tarde chocolate 10
Tarta frambuesa 12
2020-09-08 22:33:03 +02:00
```
2021-01-21 19:50:56 +01:00
La explicación:
* `:%!` aplica el filtro a todas las líneas \(`%`\).
* `awk 'NR > 1'` muestra los texto solo desde la columna 2 en adelante.
* `|` encadena esto con el siguiente comando.
* `sort -nk 3` ordena numéricamente \(`n`\) utilizando los valores de la columna 3 \(`k 3`\).
* `column -t` organiza el texto con los espaciados.
2020-09-08 22:33:03 +02:00
2021-01-22 19:01:06 +01:00
## Comando del modo normal
2020-09-08 22:33:03 +02:00
Vim tiene un filtro de operador \(`!`\) en el modo normal. Si tienes los siguientes saludos:
2020-09-08 22:33:03 +02:00
```text
2020-09-08 22:33:03 +02:00
hello vim
hola vim
bonjour vim
salve vim
```
2021-01-22 19:01:06 +01:00
Para convertir en mayúsculas la línea actual y la línea inferior, puedes ejecutar:
```text
2020-09-08 22:33:03 +02:00
!jtr '[a-z]' '[A-Z]'
```
2021-01-22 19:01:06 +01:00
La explicación:
2020-09-08 22:33:03 +02:00
* `!j` ejecuta el filtro operador del comando normal \(`!`\) en la línea actual y la línea inferior. Recuerda que es un operador del modo normal, la regla gramática de `verbo + sustantivo` se aplica en este caso.
* `tr '[a-z]' '[A-Z]'` reemplaza las letras minúsculas con letras mayúsculas.
El filtro del comando normal solo funciona en movimientos u objetos de texto que tengan al menos una línea o más. Si intentas ejecutar `!iwtr '[a-z]' '[A-Z]'` \(ejecutar `tr` dentro de la palabra donde está el cursor\), verás que se aplica el comando `tr` a la línea completa, no a la palabra sobre la que está el cursor.
2020-09-08 22:33:03 +02:00
2021-01-22 19:01:06 +01:00
## Aprender los comandos externos de la manera más inteligente
2020-09-08 22:33:03 +02:00
Vim no es un entorno de desarrollo integrado \(o IDE por sus siglas en inglés\). Es un editor modal ligero que por diseño es altamente extensible. Debido a esa propiedad de ser extensible, tienes un acceso sencillo a los comandos externos de tu sistema. Con esto, Vim está un paso más cerca de convertirse en un IDE. Alguien dijo alguna vez que el sistema Unix es el primer IDE que ha existido.
El comando _bang_ es tan útil como el número de comandos que conozcas. No te preocupes si tienes un conocimiento limitado de los comando modernos. Siempre hay que estar aprendiendo nuevos comandos, toma esto como una motivación para seguir aprendiendo. Cada vez que necesites filtrar un texto, echa un vistazo si existe un comando externo que pueda solucionar tu problema. No te preocupes en dominar todo sobre un comando en particular. Simplemente aprende los que necesites para realizar tu tarea actual.
2020-09-08 22:33:03 +02:00