sh shell 不支持 $@ 上的参数扩展吗?

sh shell 不支持 $@ 上的参数扩展吗?

我已经发布一个答案关于 AU 的一个问题,我发现参数扩展$@不适用于shshell:

<infile xargs -d'\n' sh -c 'echo "${@%%/*}"' _

但它在bash.这是 shell 的预期行为吗sh?我如何在那里执行扩展?

此外,我知道通过-n1选项xargs我一次只能将一行传递给命令,但我对是否sh可以扩展感兴趣$@

<infile xargs -d'\n' -n1 sh -c 'echo "${0%%/*}"'

infile包含:

A1 /B1/C1
A 2/B2/C2
A3/B3/C3

答案1

是的,破折号在这里似乎不太有用。虽然这并没有错,但严格来说,确实${@%...}如此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>

相关内容