Comment changer un argument de ligne de commande dans Bash?

94

Existe-t-il un moyen de modifier les arguments de ligne de commande dans un script Bash. Disons par exemple qu'un script Bash est appelé de la manière suivante:

./foo arg1 arg2  

Existe-t-il un moyen de modifier la valeur de arg1 dans le script? Dis, quelque chose comme

$1="chintz"
Sriram
la source

Réponses:

150

Vous devez réinitialiser tous les arguments. Pour changer par exemple $3:

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

En gros, vous définissez tous les arguments sur leurs valeurs actuelles, à l'exception de celui (s) que vous souhaitez modifier. set --est également spécifié par POSIX 7 .

La "${@:1:2}"notation est étendue aux deux 2arguments de position (d'où les dans la notation) à partir de offset 1(ie $1). C'est un raccourci pour "$1" "$2"dans ce cas, mais il est beaucoup plus utile lorsque vous souhaitez remplacer par exemple "${17}".

Thkala
la source
1
Donc, pour changer 3 $, je dois aussi changer 1 $ et 2 $, n'est-ce pas? Et les changer en quoi? Que signifie «réinitialiser»?
Sriram
Merci pour l'astuce! J'ai eu du mal à l'utiliser pour les noms de fichiers avec des espaces intégrés. Pour toute autre personne qui peut courir dans ce problème, essayez de mettre evalà l'avant de la ligne par ce .
cxw
2
C'est correct lorsque vous connaissez la position du paramètre que vous souhaitez modifier. Que faire si vous ne le connaissez pas et avez besoin de le changer dynamiquement? J'ai essayé avec $ set - "$ {: 1: $ pivot}" mais il n'accepte pas de variable ici.
Daniele Segato
1
Comment puis-je faire la même chose depuis l'intérieur d'une fonction? Votre solution ne semble pas fonctionner lorsqu'elle est appelée depuis l'intérieur d'une fonction.
Hashken
2
Vous ne pouvez pas modifier les paramètres de position d'un script à partir d'une fonction - les propres arguments de la fonction les masquent. Vous pouvez, cependant, les stocker dans un tableau et les utiliser.
thkala
23

Optimisation pour la lisibilité et la maintenabilité, vous pouvez être mieux assigner $1et $2à des variables plus significatives (je ne sais pas, input_filename = $1et output_filename = $2ou quelque chose), puis une de ces écraser les variables ( input_filename = 'chintz'), laissant l'entrée au script inchangé, dans le cas où il est nécessaire ailleurs.

Johnsyweb
la source
Je voulais une approche où je pourrais modifier l'un des arguments d'entrée lui-même. J'avais besoin de le faire car je voulais renvoyer une valeur du script. La réponse suggérée par thkala a bien fonctionné. Merci pour la réponse!!!
Sriram le
3
@Johnsyweb D'accord. Pour des raisons de lisibilité, la vôtre est la meilleure méthode.
Dss
1
"Vous êtes mieux" dépend toujours du cas d'utilisation, qui n'est pas fourni.
Scott
2
@Scott 7 ans de plus et plus d'expérience que moi lorsque j'ai écrit cette réponse, je suis enclin à être d'accord avec vous.
Johnsyweb
Exemple où cela ne fonctionnerait pas (à part l'utilisation de quelque chose comme $ FIRST_PARAMETER): avoir l'utilisation et la signification du paramètre en fonction de la valeur réelle.
Igor Stoppa