J'ai un script simple où le premier argument est réservé pour le nom de fichier, et tous les autres arguments facultatifs doivent être passés à d'autres parties du script.
En utilisant Google, j'ai trouvé ce wiki , mais il a fourni un exemple littéral:
echo "${@: -1}"
Je ne peux rien faire d'autre, comme:
echo "${@:2}"
ou
echo "${@:2,1}"
J'obtiens "Mauvaise substitution" du terminal.
Quel est le problème et comment puis-je traiter tout sauf le premier argument passé à un script bash?
"{@:2}"
qui a provoqué un échec , c'est pourquoi la bonne réponse correspond ci-dessus.Réponses:
Utilisez ceci:
La syntaxe suivante:
fonctionnerait également, mais n'est pas recommandé, car comme @Gordon l'a déjà expliqué, l'utilisation
*
, il exécute tous les arguments ensemble comme un seul argument avec des espaces, tout en@
préservant les interruptions entre eux (même si certains des arguments eux-mêmes contiennent des espaces ). Cela ne fait pas la différence avececho
, mais c'est important pour de nombreuses autres commandes.la source
#!/usr/bin/env sh
c'est pourquoi j'ai eu des problèmes. Votre exemple fonctionne bien, comme ci-dessus, après avoir retiré ce shebang"${@:2}"
place - l'utilisation*
exécute tous les arguments ensemble comme un seul argument avec des espaces, tout en@
préservant les sauts entre eux (même si certains des arguments eux-mêmes contiennent des espaces). La différence n'est pas perceptible avececho
, mais elle compte pour bien d'autres choses.echo
est assez indulgent pour les concaténer pour vous; d'autres commandes pourraient ne pas être aussi agréables. Ne vous contentez pas d'utiliser l'un ou l'autre: apprenez la différence entre*
et@
et quand les utiliser. Vous devriez les utiliser à peu près également. Un bon exemple de quand ce sera un problème: si$3
contient un saut de ligne (\n
), il sera remplacé par un espace, à condition que vous ayez une$IFS
variable par défaut .echo
juste utilisé comme exemple - auquel cas ils ne devraient pas être exécutés ensemble. D'après mon expérience, les situations où vous voulez les faire fonctionner ensemble sont rares (voir cette question pour un exemple ), et"$@"
c'est presque toujours ce que vous voulez. En outre, le problème que vous mentionnez avec un saut de ligne se produit uniquement si$@
(ou$*
) n'est pas entre guillemets.$*
assez souvent dans mes scripts.Si vous voulez une solution qui fonctionne également dans
/bin/sh
tryshift [n]
décale les paramètres de position n fois. Ashift
définit la valeur de$1
sur la valeur de$2
, la valeur de$2
sur la valeur de$3
, etc., en diminuant la valeur de$#
un.la source
foo=shift
ne fait pas ce à quoi je m'attendais.foo=$(shift)
shift
(dans le shell) n'a pas de sortie. Il jette tout simplement$1
et décale tout. 2)$(...)
démarre un sous-shell, qui a ses propres arguments locaux. Il déplace les arguments dans le sous-shell, ce qui n'affecte pas le parentsomecommand "$1" "${@:2}"
avec cette méthode (c.-à-d. Déplacer "en ligne")?http://wiki.bash-hackers.org/scripting/posparams
Il explique l'utilisation de
shift
(si vous souhaitez supprimer les premiers N paramètres), puis la mise en œuvre de l'utilisation de massela source
Je suis tombé sur cette recherche de quelque chose d'autre. Bien que la publication semble assez ancienne, la solution la plus simple dans bash est illustrée ci-dessous (au moins bash 4) en utilisant
set -- "${@:#}"
où # est le numéro de départ de l'élément de tableau que nous voulons conserver en avant:Fondamentalement, le
set -- "${@:3}"
juste saute les deux premiers éléments du tableau comme le décalage de perl et préserve tous les éléments restants, y compris le troisième. Je soupçonne qu'il existe également un moyen de masquer les derniers éléments.la source