Al ejecutar un script de shell, ¿es posible pasar parámetros posicionales específicos sin tener que ingresarlos todos en orden?

13

Por ejemplo, si tengo un script ./foo que toma 10 parámetros, y solo quiero pasar el octavo parámetro. La única forma en que sé cómo hacer esto actualmente es:

./foo '' '' '' '' '' '' '' 'bar'

¿Hay una manera más fácil / mejor?

Kerry Randolph
fuente
1
Esta es la razón por la cual los programas generalmente usan opciones en lugar de parámetros posicionales si tiene muchos parámetros.
Barmar

Respuestas:

4

Otra forma de hacer esto es nombrar el parámetro que desea declarar y luego hacerlo:

{   cat >./foo 
    chmod +x ./foo
    eight=declared ./foo
    eight=declared_and_preferred \
        ./foo 1 2 3 4 5 6 7 8
    ./foo 1 2 3 4 5 6 7 8
    ./foo
} <<\SCRIPT
#!/usr/bin/sh
: ${eight:=${8:-some_default}}
printf '$eight = %s\n' "$eight"
#END
SCRIPT

SALIDA

$eight = declared
$eight = declared_and_preferred
$eight = 8
$eight = some_default

En el ejemplo anterior, la variable de entorno declarada explícitamente se prefiere al argumento de la línea de comandos, pero el argumento de la línea de comandos se utiliza cuando la variable de entorno está vacía o sin establecer. Cuando tanto la octava posición como la variable de entorno $eightestán vacías o desarmadas, se asigna el valor predeterminado some_default$eight . En cualquier caso, :puede eliminarse de las declaraciones :-o :=si está vacío debe ser un valor aceptable.

La variable también $eightpodría haberse configurado como:

printf '$eight = %s\n' "${eight:=${8:-some_default}}"

... y la línea anterior se omitió por completo, pero quería demostrar que declarar una variable de esa manera da como resultado un valor persistente, y así lo hice en dos comandos. De cualquier manera $eightse establece el valor final de la expansión de ese parámetro compuesto.

getopts- para secuencias de comandos robustas: a menudo es la mejor manera de manejar las opciones de comando . Los parámetros posicionales, por otro lado, son casi siempre el medio más simple de manejar de manera robusta los operandos en un script.

Por ejemplo:

touch file$(seq -ws\ file 100)
./foo *

SALIDA

$eight = file008

Allí solo vemos el octavo operando, pero hay 101 de ellos en mi directorio de prueba.

mikeserv
fuente
18

Suponiendo que puede cambiar el script, debería considerar el uso de parámetros opcionales (opciones) en lugar de los parámetros requeridos (argumentos).

Si tiene cada uno de los primeros 7 siete parámetros como opciones, y los tiene por defecto en la cadena vacía, entonces simplemente podría hacer:

./foo bar

Si usa un shell compatible con POSIX, puede usar la getoptsutilidad o el programa getopt. bash- como la mayoría de los proyectiles - se ofrece getoptscomo una función integrada. De cualquier manera es más fácil que rodar su propio analizador de línea de comandos.

A menos que implemente algo como los últimos argumentos de X sin opciones, los valores de los últimos argumentos de Y y XY tienen que proporcionar cadenas de opciones antes de cada una de las 7 cadenas (ahora vacías) si desea establecer cualquiera de ellos. Sin embargo, esto no es una práctica común, normalmente una opción siempre es una opción y un argumento un argumento, y el orden de la opción "inserción" es libre.

Anthon
fuente
55
+1para getopt(s). Los parámetros posicionales son un momento triste y deben evitarse.
HalosGhost