Да, черточка здесь менее чем полезна. Хотя, строго говоря, это не вина, как ${@%...}
это не указано в POSIX :
Следующие четыре разновидности расширения параметров обеспечивают обработку подстроки. [...] Если параметр равен ' #
', ' *
' или ' @
', результат раскрытия не указан.
Странно, хотя, кажется, что если подобное расширение изменяет конец одного позиционного параметра, оно отбрасывает следующие. Но не, если это фактически не изменяет конец:
$ 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 и Zsh, кажется, обрабатывают "${@#...}"
и "${@%...}"
обрабатывают каждый позиционный параметр независимо, что может показаться полезным.
Я предполагаю, что очевидный обходной путь для dash
заключается в том, чтобы модифицировать один аргумент за раз:
for x in "$@"; do echo "${x%%/*}"; done
Что бы это ни стоило, поведение используемых расширений для удаления префикса / суффикса $*
также зависит от оболочки. Bash и ksh сначала изменяют параметры, а затем присоединяют их, тогда как Zsh и dash сначала присоединяют параметры и изменяют объединенную строку:
$ zsh -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a>
$ bash -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a b>
sh
думает, что$@
является единственным параметром для всего файла (или будет разбит на несколько, если превысит ARG_MAX) и сделает расширение только для одного аргумента.Bad substitution
ошибку в этом коде. Ибо${*%pattern}
вы видите некоторые различия в поведении в таких вещах, как"$shell" -c 'printf "<%s>\n" "${*%x*}"' sh ax by
ARG_MAX
, что это связано с тем, что обработка является внутренней для оболочки.