Oui, le tiret semble moins utile ici. Bien qu'il ne soit pas en faute, à proprement parler, comme cela ${@%...}
n'est pas spécifié par POSIX :
Les quatre variétés d'expansion de paramètres suivantes permettent le traitement de la sous-chaîne. [...] Si le paramètre est ' #
', ' *
' ou ' @
', le résultat de l'expansion n'est pas spécifié.
C'est bizarre cependant, il semble que si une expansion comme celle-ci modifie la fin d'un paramètre positionnel, elle supprime les suivants. Mais pas s'il ne modifie pas réellement la fin:
$ dash -c 'set -- foo bar; printf "<%s>\n" "${@%o}";'
<fo>
$ dash -c 'set -- foo bar; printf "<%s>\n" "${@%x}";'
<foo>
<bar>
$ dash -c 'set -- foo bar doo; printf "<%s>\n" "${@%r}";'
<foo>
<ba>
Bash, ksh et Zsh semblent tous gérer "${@#...}"
et "${@%...}"
en traitant indépendamment chaque paramètre de position, ce qui semble la chose utile à faire.
Je suppose que la solution de contournement évidente consiste dash
à effectuer la modification un argument à la fois:
for x in "$@"; do echo "${x%%/*}"; done
Pour ce que ça vaut, le comportement des extensions de suppression de préfixe / suffixe utilisées $*
varie également entre les shells. Bash et ksh semblent modifier les paramètres en premier et les rejoindre ensuite, tandis que Zsh et dash rejoignent les paramètres en premier et modifient la chaîne concaténée:
$ zsh -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a>
$ bash -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a b>
sh
pense que$@
c'est un paramètre unique pour tout le fichier (ou se divisera en plusieurs si dépassent ARG_MAX) et fait une expansion sur le seul argument.Bad substitution
erreur sur ce code. Car${*%pattern}
, vous voyez des variations de comportement dans des choses comme"$shell" -c 'printf "<%s>\n" "${*%x*}"' sh ax by
ARG_MAX
entre en jeu, que le traitement est interne au shell.