Argumentos de la línea de comandos en Node.js

Los argumentos de la línea de comandos son cadenas de texto que se utilizan para pasar información adicional a un programa cuando se ejecuta una aplicación a través de la interfaz de línea de comandos (CLI)...

¿Qué son los argumentos de la línea de comandos?

Los argumentos de la línea de comandos son cadenas de texto que se utilizan para pasar información adicional a un programa cuando se ejecuta una aplicación a través de la interfaz de línea de comandos (CLI) de un sistema operativo Los argumentos de la línea de comandos suelen incluir información utilizada para establecer la configuración o los valores de propiedad de una aplicación.

En la mayoría de los casos, los argumentos se pasan después del nombre del programa en su solicitud. Un ejemplo de la sintaxis de los argumentos de la línea de comandos se ve así:

1
$ [runtime] [script_name] [argument-1 argument-2 argument-3 ... argument-n]

Aquí el tiempo de ejecución puede ser cualquier cosa que ejecute un programa/script, p. sh, java, node, etc. Los argumentos generalmente están separados por un espacio; sin embargo, hay algunos tiempos de ejecución que usan comas para distinguir entre múltiples argumentos de línea de comando. Además, según el programa, puede pasar argumentos en forma de pares clave-valor, que veremos más adelante en este artículo.

¿Por qué utilizar argumentos de línea de comandos? {#por qué usar argumentos lineales de comando}

Los siguientes son algunos de los principales beneficios de usar argumentos de línea de comandos:

  • Puede pasar información a una aplicación antes de que comience. Esto es particularmente útil si desea realizar ajustes de configuración de gran número.
  • Los argumentos de la línea de comandos se pasan como cadenas a su programa. Los tipos de datos de cadena se pueden convertir fácilmente a otros tipos de datos dentro de una aplicación, lo que hace que los argumentos sean muy flexibles.
  • Puede pasar un número ilimitado de argumentos a través de la línea de comando.
  • Los argumentos de la línea de comandos se utilizan junto con secuencias de comandos y archivos por lotes, lo que resulta particularmente útil para las pruebas automatizadas.

Y aquí están algunas de las desventajas de usarlos:

  • La mayor desventaja de pasar información a través de la línea de comandos es que la interfaz tiene una curva de aprendizaje pronunciada, por lo que es difícil de usar para la mayoría de las personas a menos que tengan mucha experiencia en el uso de herramientas CLI.
  • Las aplicaciones de línea de comandos pueden ser difíciles de usar a menos que esté usando una computadora de escritorio o portátil, por lo que normalmente no se usan en dispositivos más pequeños como teléfonos o tabletas.

Paso de argumentos de línea de comandos en Node.js

Como muchos otros lenguajes, las aplicaciones de Node.js también aceptan argumentos de línea de comandos. De forma predeterminada, Node se encargará de aceptar los argumentos por usted, pero también hay algunos paquetes de terceros excelentes que agregan algunas funciones muy útiles.

En esta sección, le mostraremos cómo usar argumentos de forma integrada (process.argv), así como con los populares paquetes minimist y yargs.

Usando process.argv

La forma más sencilla de recuperar argumentos en Node.js es a través de la matriz process.argv. Este es un objeto global que puede usar sin importar bibliotecas adicionales para usarlo. Simplemente necesita pasar argumentos a una aplicación Node.js, tal como mostramos anteriormente, y se puede acceder a estos argumentos dentro de la aplicación a través de la matriz process.argv.

El primer elemento de la matriz process.argv siempre será una ruta del sistema de archivos que apunta al ejecutable node. El segundo elemento es el nombre del archivo JavaScript que se está ejecutando. Y el tercer elemento es el primer argumento que realmente pasó el usuario.

Para evitar confusiones, me gustaría recordarles a los principiantes que JavaScript usa índices basados ​​en cero en matrices (como muchos otros idiomas), lo que significa que el primer elemento se almacenará en el índice "0th" y el último elemento se almacenará en el índice "n-1", donde "n" es el número total de elementos en la matriz.

Ahora, escribamos un script de Node simple que imprima todos los argumentos de la línea de comando pasados ​​a la aplicación, junto con su índice. Copie y pegue el siguiente código en un archivo llamado "processargv.js".

1
2
3
4
5
'use strict';

for (let j = 0; j < process.argv.length; j++) {
    console.log(j + ' -> ' + (process.argv[j]));
}

Todo lo que hace este script es recorrer la matriz process.argv e imprimir los índices, junto con los elementos almacenados en esos índices. Es muy útil para la depuración si alguna vez te preguntas qué argumentos estás recibiendo y en qué orden.

Ahora, para ejecutar este tipo, escriba el siguiente comando. Solo asegúrese de estar en el directorio donde se guarda el archivo "processargv.js".

1
$ node processargv.js tom jack 43

Aquí estamos pasando tres argumentos al programa "processargv.js". Verá que "tom" se almacenará en el segundo índice, mientras que "jack" y "43" se almacenarán en el tercer y cuarto índice, respectivamente. La salida debería ser algo como esto:

1
2
3
4
5
6
$ node processargv.js tom jack 43
0 -> /Users/scott/.nvm/versions/node/v4.8.0/bin/node
1 -> /Users/scott/javascript/processargv.js
2 -> tom
3 -> jack
4 -> 43

Puede ver que el primer índice contiene la ruta a nuestro ejecutable node (que probablemente tendrá una ruta diferente a la mía), el segundo índice contiene la ruta al archivo de script y el resto de los índices contienen los argumentos que pasamos en su respectiva secuencia.

Usando el módulo minimalista

Otra forma de recuperar los argumentos de la línea de comandos en una aplicación Node.js es usar el módulo minimalista. El módulo minimist analizará los argumentos de la matriz process.argv y la transformará en una matriz asociativa más fácil de usar. En la matriz asociativa, puede acceder a los elementos a través de nombres de índice además de los números de índice. Echa un vistazo al siguiente ejemplo.

1
2
3
4
5
6
'use strict';

const args = require('minimist')(process.argv.slice(2));

console.log(args);
console.log(args.i);

Guarde el código anterior en "minimist.js". En el código anterior usamos el método slice del objeto global process.argv. El método slice, en este caso, elimina todos los elementos anteriores de la matriz a partir del índice que se le pasó como parámetro. Aquí sabemos que el argumento que pasamos manualmente se almacena a partir del segundo índice, pasamos 2 a la función de corte. Luego imprimimos todo el objeto args. También imprimimos un solo elemento de la matriz utilizando el índice nombrado, es decir, "i", en lugar del número de índice.

Ahora, cuando le pasamos un argumento a este programa, también podemos especificar el carácter por el que queremos acceder al elemento. Dado que en el script usamos el nombre de índice "i" para acceder al elemento, debemos especificar el elemento almacenado en este índice. Eche un vistazo al script para ejecutar el programa anterior.

1
$ node minimist.js i jacob j 45

Observe aquí que especificamos "i" como el nombre del segundo índice, el valor almacenado en ese índice es "jacob". De manera similar, el tercer índice se denomina "j" y el valor de este índice es 45. El resultado del comando anterior será el siguiente:

1
2
3
$ node minimist.js -i jacob -j 45
{ _: [], i: 'jacob', j: 45 }
jacob

Si bien no es tan rico en funciones como algunos de los otros módulos de análisis de argumentos (ver yargs a continuación), minimist tiene algunas funciones útiles que quizás desee consultar, como alias y valores predeterminados.

Si configura un alias, la persona que llama a su programa puede usar el alias además del nombre de la opción normal. Esto es útil si desea tener una notación abreviada para sus opciones, como se ve a continuación:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
'use strict';

const minimist = require('minimist');

let args = minimist(process.argv.slice(2), {
    alias: {
        h: 'help',
        v: 'version'
    }
});

console.log('args:', args);

Llamar a este código con la opción -h establece h: true y help: true en los argumentos de salida:

1
2
$ node minimist-alias.js -h
args: { _: [], h: true, help: true }

En cuanto a la función predeterminada de minimist, si no se pasa ningún valor para una opción, se utilizará automáticamente el valor predeterminado que establezca en su programa.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
'use strict';

const minimist = require('minimist');

let args = minimist(process.argv.slice(2), {
    default: {
        port: 8080
    },
});

console.log('args:', args);

Llamar a este código sin la opción -port todavía te da un valor port en el objeto args devuelto:

1
2
$ node minimist-defaults.js
args: { _: [], port: 8080 }

Para obtener más opciones, consulte el LÉAME.

Uso del módulo yargs

Otro módulo para ayudarlo a analizar los argumentos de la línea de comandos pasados ​​a los programas de Node es el módulo yargos. Con este módulo, puede pasar argumentos en forma de pares clave-valor y luego acceder a los valores de los argumentos en su programa usando las claves correspondientes.

Nota: Puedes instalar el módulo yargs con el siguiente comando:

1
$ npm install yargs

Ahora, echa un vistazo al siguiente script:

1
2
3
4
5
6
'use strict';

const args = require('yargs').argv;

console.log('Name: ' + args.name);
console.log('Age: ' + args.age);

En la secuencia de comandos anterior, mostramos los valores proporcionados para los argumentos 'nombre' y 'edad', que se pasaron a través de la línea de comando. Ahora guarde el script anterior en un archivo llamado "yargs.js".

Nota: Cuando ejecuta el programa anterior, debe pasar los valores para los argumentos 'nombre' y 'edad'; de lo contrario, se proporcionará “indefinido” para los argumentos de forma predeterminada y verá “indefinido” escrito en la consola.

Para ejecutar el programa anterior, ejecute el siguiente comando en su indicador:

1
$ node yargs.js --name=jacob --age=45

Aquí estamos pasando valores para los argumentos de nombre y edad. La salida del script anterior se verá así:

1
2
3
$ node yargs.js --name=jacob --age=45
Name: jacob
Age: 45

El paquete yargs es muy poderoso, no solo proporciona las funciones estándar de análisis de argumentos, sino también muchas funciones avanzadas. Si bien no repasaremos todas las funciones en este artículo, al menos mencionaremos una de sus funciones más populares.

Una de las formas más poderosas de usar yargs es la opción .command(), que lo ayuda a crear, exponer y llamar a las funciones de Node a través de la línea de comando. Aquí hay un ejemplo simple de esta función en acción:

1
2
3
4
5
6
7
8
'use strict';

const argv = require('yargs')
    .command('upload', 'upload a file', (yargs) => {}, (argv) => {
        console.log('Uploading your file now...');

        // Do stuff here
    }).argv;

Llamar a este programa con el comando "upload" invocará la función que le pasó, que en este caso solo se imprime en la línea de comando. Sin embargo, estoy seguro de que puede imaginar pasar una función mucho más capaz que usa el objeto argv analizado para determinar qué archivo enviar a dónde.

Por ejemplo, este comando podría llamarse así (suponiendo que el código anterior esté almacenado en un archivo llamado "s3-tool.js":

1
2
$ node s3-tool.js upload --file=my-file.txt --bucket=my-s3-bucket
Uploading your file now...

Y no tiene que detenerse ahí, incluso puede crear un comando predeterminado:

1
2
3
4
5
6
'use strict';

const argv = require('yargs')
    .command('*', 'the default command handler', () => {}, (argv) => {
        console.log('This function is called by default');
    }).argv;

La función .command() es incluso lo suficientemente potente como para inferir los parámetros obligatorios y opcionales de una cadena:

1
2
3
4
5
'use strict';

const yargs = require('yargs');

yargs.command('login <username> [password]', 'authenticate with the server').argv

Para obtener más información sobre las funciones avanzadas, consulte yargs [documentación avanzada del tema] (https://github.com/yargs/yargs/blob/HEAD/docs/advanced.md).

Conclusión

Puede que le sorprenda un poco, pero como habrá notado, el análisis de argumentos puede ser un tema bastante complejo. Dependiendo de tus necesidades puedes hacerlo tan simple o complicado como quieras. Independientemente, existe una solución adecuada para todas las necesidades, ya sea la matriz process.argv básica o el poderoso paquete yargs.

¿Cómo has usado minimist y yargs para crear programas CLI? ¡Cuéntanos en los comentarios!