我已经发布一个答案关于 AU 的一个问题,我发现参数扩展$@
不适用于sh
shell:
<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>