Sí, el guión parece ser menos que útil aquí. Aunque no es la culpa, en sentido estricto, como ${@%...}
es especificado por POSIX :
Las siguientes cuatro variedades de expansión de parámetros proporcionan procesamiento de subcadenas. [...] Si el parámetro es ' #
', ' *
' o ' @
', el resultado de la expansión no está especificado.
Sin embargo, es extraño, parece que si una expansión como esa modifica el final de un parámetro posicional, deja caer los siguientes. Pero no si en realidad no modifica el final:
$ 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 y Zsh parecen manejar "${@#...}"
y "${@%...}"
procesar cada parámetro posicional de forma independiente, lo que parece lo más útil.
Supongo que la solución obvia para dash
es hacer la modificación de un argumento a la vez:
for x in "$@"; do echo "${x%%/*}"; done
Por lo que vale, el comportamiento de las expansiones de eliminación de prefijos / sufijos utilizados $*
también varía entre shells. Bash y ksh parecen modificar los parámetros primero y unirse a ellos después de eso, mientras que Zsh y dash unen los parámetros primero y modifican la cadena concatenada:
$ zsh -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a>
$ bash -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a b>
sh
piensa que$@
es un parámetro único para todo el archivo (o se romperá en múltiples si excede ARG_MAX) y se expandirá en el único argumento.Bad substitution
error en ese código. Para${*%pattern}
, ves alguna variación en el comportamiento en cosas como"$shell" -c 'printf "<%s>\n" "${*%x*}"' sh ax by
ARG_MAX
suceda, ese procesamiento es interno al shell.