Answers:
是的,破折号似乎在这里没有用。虽然它是没有过错的,严格来说,作为${@%...}
是不确定的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
值得的是,$*
shell之间使用的前缀/后缀删除扩展的行为也有所不同。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>
Bad substitution
在该代码上出错。对于${*%pattern}
,你看到在行为之类的一些变化"$shell" -c 'printf "<%s>\n" "${*%x*}"' sh ax by
ARG_MAX
涉及到处理是外壳内部的。
sh
认为$@
是整个文件的单个参数(或将打破多个,如果超过ARG_MAX)和做的唯一理由扩张。