¿Cómo cambiar un argumento de línea de comando en Bash?

94

¿Hay alguna forma de cambiar los argumentos de la línea de comandos en un script Bash? Digamos, por ejemplo, que un script Bash se invoca de la siguiente manera:

./foo arg1 arg2  

¿Hay alguna forma de cambiar el valor de arg1 dentro del script? Di algo como

$1="chintz"
Sriram
fuente

Respuestas:

150

Tienes que restablecer todos los argumentos. Para cambiar, por ejemplo $3:

$ set -- "${@:1:2}" "new" "${@:4}"

Básicamente, establece todos los argumentos en sus valores actuales, excepto el (los) que desea cambiar. set --también está especificado por POSIX 7 .

La "${@:1:2}"notación se expande a los dos 2argumentos posicionales (de ahí en la notación) que comienzan desde el desplazamiento 1(es decir $1). Es una abreviatura de "$1" "$2"en este caso, pero es mucho más útil cuando desea reemplazar, por ejemplo "${17}".

thkala
fuente
1
entonces, para cambiar $ 3, debo cambiar $ 1 y $ 2 también, ¿verdad? ¿Y cambiarlos a qué? ¿Qué significa "reiniciar"?
Sriram
¡Gracias por el truco! Tuve dificultades para usar esto para nombres de archivos con espacios incrustados. Para cualquier otra persona que pueda tener ese problema, intente ponerse evalal principio de la línea según esto .
cxw
2
Esto está bien cuando conoce la posición del parámetro que desea cambiar. ¿Qué pasa si realmente no lo sabe y necesita cambiarlo de forma dinámica? Intenté con $ set - "$ {: 1: $ pivot}" pero no acepta una variable allí.
Daniele Segato
1
¿Cómo puedo hacer lo mismo desde dentro de una función? Su solución no parece funcionar cuando se invoca desde dentro de una función.
Hashken
2
No puede cambiar los parámetros posicionales de un script desde dentro de una función; los propios argumentos de la función los ocultan. Sin embargo, puede almacenarlos en una matriz y operar con eso.
thkala
23

Optimización para la legibilidad y facilidad de mantenimiento, que puede ser mejor asignación $1y $2de las variables más significativas (que no sé, input_filename = $1y output_filename = $2o algo así) y luego sobrescribir una de esas variables ( input_filename = 'chintz'), dejando la entrada a la secuencia de comandos sin cambios, en caso de que se necesario en otro lugar.

Johnsyweb
fuente
Quería un enfoque en el que pudiera alterar uno de los argumentos de entrada en sí. Necesitaba hacer eso porque quería devolver un valor del script. La respuesta sugerida por thkala funcionó bien. ¡¡¡Gracias por la respuesta!!!
Sriram
3
@Johnsyweb De acuerdo. En aras de la legibilidad, el suyo es el mejor método.
Dss
1
"Usted está mejor" siempre depende del caso de uso, que no se proporciona.
Scott
2
@Scott 7 años mayor y con más experiencia que yo cuando escribí esta respuesta, me inclino a estar de acuerdo contigo.
Johnsyweb
Ejemplo en el que esto no funcionaría (aparte de usar algo como $ FIRST_PARAMETER): tener el uso y significado del parámetro dependiendo del valor real.
Igor Stoppa