# Capturar los argumentos pasados desde la terminal en un vector
<- commandArgs(trailingOnly = TRUE)
args
# Contar cuántos argumentos nos pasaron
cat("Nos pasaron", length(args), "argumentos.\n\n")
# Mostrar los argumentos que nos pasaron
cat("Los argumentos que nos pasaron son:\n")
cat(args, "\n")
# Aunque los argumentos sean números, son tomados como carácter
cat("\nLos argumentos se toman como valores de tipo:\n")
typeof(args)
21 Uso de argumentos en la línea de comandos al ejecutar código de R
En este capítulo de lectura opcional exploraremos ejemplos más avanzados de interacción entre R y la terminal, centrándonos en el uso de argumentos que se pasan al ejecutar scripts con Rscript
. Aprenderemos cómo capturar y procesar estos argumentos con la función commandArgs()
, cómo validar su cantidad y contenido, y cómo convertirlos a otros tipos de datos cuando sea necesario. También veremos ejemplos prácticos y mencionaremos herramientas adicionales que permiten gestionar opciones de manera más sofisticada.
En ejemplos anteriores hemos visto cómo capturar distintas piezas de información de forma interactiva mediante la función scan()
mientras estamos ejecutando un programa de R desde la terminal. En otras ocasiones, en lugar de pausar la ejecución del programa a la espera de que el usuario ingrese algún valor, es conveniente especificar algunas opciones directamente en la línea de comando, al lado instrucción Rscript
que ejecuta el código.
Por ejemplo, imaginemos que tenemos un programa llamado resumen.R
que se encarga de hacer un análisis descriptivo de un conjunto de datos, guardados en algún archivo cuyo nombre debe especificar el usuario para que el programa lo lea. Supongamos también que el nombre del archivo de datos es mayo.txt
. El usuario puede mandar a correr el programa que hace el análisis sobre este archivo de datos indicando su nombre como un argumento adicional de esta forma:
Rscript resumen.R mayo.txt
Ahora pensemos que este mismo tipo de análisis se repite todos los meses con datos nuevos. En lugar de modificar nuestro script resumen.R
para que lea un archivo con otro nombre, ejecutamos lo anterior con el nombre del archivo que corresponda y listo:
Rscript resumen.R junio.txt
Rscript resumen.R julio.txt
Rscript resumen.R agosto.txt
Para que esto funcione, el programa que está guardado en resumen.R
debe ser capaz de capturar el nombre del archivo que tiene leer y que el usuario se lo está pasando como un argumento adicional en la instrucción Rscript
.
La función que se encarga de capturar los argumentos adicionales que enviamos desde la terminal es commandArgs()
. Toma todos los elementos que escribamos al final de la línea de Rscript
y los reúne en un vector atómico de tipo carácter.
En la Unidad 1 mencionamos que los vectores atómicos pueden contener más de un valor, pero hasta acá no los usamos de esa forma. Lo veremos recién en la próxima unidad. Los ejemplos que siguen hacen uso de vectores con varios elementos, que se corresponden con todos los argumentos que un usuario envía desde la terminal. Por esta razón, es recomendable que sigas leyendo si ya sabés usar vectores con más de un elemento, o que vuelvas a ver estos ejemplos más adelante, después de que hayas estudiado la unidad 5.
Los scripts utilizados en los ejemplos pueden ser descargados desde este archivo comprimido.
En primer lugar vamos a analizar al script ejemplo1.R
, con el siguiente contenido:
Vamos a ejecutarlo desde la terminal con los argumentos “hola”, “chau” y “4”. Obtenemos:
Rscript ejemplo1.R hola chau 4
Nos pasaron 3 argumentos.
Los argumentos que nos pasaron son:
hola chau 4
Los argumentos se toman como valores de tipo:
[1] "character"
Si lo ejecutamos sin argumentos:
Rscript ejemplo1.R
Nos pasaron 0 argumentos.
Los argumentos que nos pasaron son:
Los argumentos se toman como valores de tipo:
[1] "character"
Ahora vamos a suponer que el programa ejemplo2.R
tiene como objetivo contar un chiste o decir un refrán, según lo que se le pida en el único argumento que se le pasa al correrlo desde la terminal. Si el argumento es igual a “chiste”, se cuenta el chiste; si es igual a “refran” se cuenta el refrán; y en otro caso no se hace nada. El contenido del archivo es:
# Capturar los argumentos pasados desde la terminal en un vector
<- commandArgs(trailingOnly = TRUE)
args
if (args[1] == "chiste") {
cat("- Juan, cómo has cambiado.\n- Yo no soy Juan.\n- Más a mi favor.\n\n")
else if (args[1] == "refran") {
} cat("No por mucho madrugar amanece más temprano.\n\n")
else {
} # Genero un error para que el programa se detenga, avisando lo que pasa
stop("El argumento provisto debe ser igual a chiste o refran.\n")
}
Ejecutamos este archivo pasando distintos valores para su argumento:
Rscript ejemplo2.R refran
No por mucho madrugar amanece más temprano.
Rscript ejemplo2.R chiste
- Juan, cómo has cambiado.
- Yo no soy Juan.
- Más a mi favor.
Rscript ejemplo2.R hola
Error: El argumento provisto debe ser igual a chiste o refran.
Execution halted
Podemos controlar la cantidad de argumentos admitidos generando errores en el código para aquellas situaciones donde el usuario envíe menos o más que la cantidad deseada. Por ejemplo, en el caso anterior, es obligatorio enviar uno y sólo un argumento. Modificamos el script para que lo tenga en cuenta, dando lugar al programa ejemplo3.R
:
# Capturar los argumentos pasados desde la terminal en un vector
<- commandArgs(trailingOnly = TRUE)
args
# Controlar la cantidad de argumentos
if (length(args) == 0 || length(args) > 1) {
stop("Debe proveer exactamente un argumento, que debe ser igual a chiste o refran.\n")
}
if (args[1] == "chiste") {
cat("- Juan, cómo has cambiado.\n- Yo no soy Juan.\n- Más a mi favor.\n\n")
else if (args[1] == "refran") {
} cat("No por mucho madrugar amanece más temprano.\n\n")
else {
} # Genero un error para que el programa se detenga, avisando lo que pasa
stop("El argumento provisto debe ser igual a chiste o refran.\n")
}
Veamos lo que pasa si cumplimos o no con la cantidad exacta de argumentos que hay que pasarle al código de R:
Rscript ejemplo3.R
Error: Debe proveer exactamente un argumento, que debe ser igual a chiste o refran.
Execution halted
Rscript ejemplo3.R chiste refran
Error: Debe proveer exactamente un argumento, que debe ser igual a chiste o refran.
Execution halted
Rscript ejemplo3.R chiste
- Juan, cómo has cambiado.
- Yo no soy Juan.
- Más a mi favor.
Imaginemos por último que es obligatorio pasar un primer argumento (“chiste” o “refran”) y que opcionalmente se puede pasar un segundo argumento, que se va a tratar de un número para indicar cuántas veces queremos que el chiste o el refrán se repita. Como todos los argumentos se pasan como datos de tipo carácter, para poder usar el número tendremos que convertirlo a dato de tipo numérico. Añadimos esta característica en el script ejemplo4.R
:
# Capturar los argumentos pasados desde la terminal en un vector
<- commandArgs(trailingOnly = TRUE)
args
# Si no proveyó argumentos, generar un error y que se detenga el programa
if (length(args) == 0) {
stop("Debe proveer al menos un argumento (chiste o refran).")
}
# Si proveyó más de 2 argumentos, generar un error y que se detenga el programa
if (length(args) > 2) {
stop("No debe proveer más de 2 argumentos. El primero es obligatorio (chiste o refran) y el segundo es opcional (un número que indica la cantidad de veces a repetir el chiste o el refrán).")
}
# Si no hay segundo argumento, args[2] es NA
if (is.na(args[2])) {
<- 1
n else {
} <- as.numeric(args[2])
n
}
# Repetir n veces
for (i in 1:n) {
if (args[1] == "chiste") {
cat("- Juan, cómo has cambiado.\n- Yo no soy Juan.\n- Más a mi favor.\n\n")
else if (args[1] == "refran") {
} cat("No por mucho madrugar amanece más temprano.\n\n")
else {
} # Genero un error para que el programa se detenga, avisando lo que pasa
stop("El argumento provisto debe ser igual a chiste o refran.\n")
} }
Veamos ahora cómo funciona:
Rscript ejemplo4.R refran 5
No por mucho madrugar amanece más temprano.
No por mucho madrugar amanece más temprano.
No por mucho madrugar amanece más temprano.
No por mucho madrugar amanece más temprano.
No por mucho madrugar amanece más temprano.
Rscript ejemplo4.R chiste 3
- Juan, cómo has cambiado.
- Yo no soy Juan.
- Más a mi favor.
- Juan, cómo has cambiado.
- Yo no soy Juan.
- Más a mi favor.
- Juan, cómo has cambiado.
- Yo no soy Juan.
- Más a mi favor.
Rscript ejemplo4.R refran
No por mucho madrugar amanece más temprano.
Rscript ejemplo4.R
Error: Debe proveer al menos un argumento (chiste o refran).
Execution halted
Además de la función commandArgs()
existen paquetes de R para poder trabajar con argumentos y opciones de formas mucho más elaboradas, como los paquetes argparse
y optparse
, entre otros.