Sì, il trattino sembra essere poco utile qui. Anche se non è esente da colpa, a rigor di termini, come ${@%...}
è specificato da POSIX :
Le seguenti quattro varietà di espansione dei parametri prevedono l'elaborazione della sottostringa. [...] Se il parametro è ' #
', ' *
' o ' @
', il risultato dell'espansione non è specificato.
È strano però, se un'espansione del genere modifica la fine di un parametro posizionale, rilascia i seguenti. Ma non se in realtà non modifica la fine:
$ 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 e Zsh sembrano tutti in grado di gestire "${@#...}"
ed "${@%...}"
elaborare ogni parametro posizionale in modo indipendente, il che sembrerebbe la cosa utile da fare.
Suppongo che l'evidente soluzione alternativa dash
sia quella di rendere la modifica un argomento alla volta:
for x in "$@"; do echo "${x%%/*}"; done
Per quello che vale, il comportamento delle espansioni di rimozione prefisso / suffisso utilizzate $*
varia anche tra le shell. Bash e ksh sembrano modificare prima i parametri e unirli successivamente, mentre Zsh e dash uniscono prima i parametri e modificano la stringa concatenata:
$ zsh -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a>
$ bash -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a b>
sh
pensa che$@
sia un singolo parametro per l'intero file (o si spezzerà in più se supera ARG_MAX) e farà l'espansione sull'unico argomento.