有没有办法从函数中设置bash脚本的位置参数?
在全局范围内,可以使用set -- <arguments>更改位置参数,但它在函数内部不起作用,因为它更改了函数的位置参数.
快速说明:
# file name: script.sh
# called as: ./script.sh -opt1 -opt2 arg1 arg2
function change_args() {
set -- "a" "c" # this doesn't change the global args
}
echo "original args: $@" # original args: -opt1 -opt2 arg1 arg2
change_args
echo "changed args: $@" # changed args: -opt1 -opt2 arg1 arg2
# desired outcome: changed args: a c
Run Code Online (Sandbox Code Playgroud)
如前所述,答案是否定的,但如果有人需要这个,可以选择设置外部数组(_ARRAY),从函数内部修改它,然后set -- ${_ARRAY[@]}在事后使用。例如:
#!/bin/bash
_ARGS=()
shift_globally () {
shift
_ARGS=$@
}
echo "before: " "$@"
shift_globally "$@"
set -- "${_ARGS[@]}"
echo "after: " "$@"
Run Code Online (Sandbox Code Playgroud)
如果你测试一下:
./test.sh a b c d
> before: a b c d
> after: b c d
Run Code Online (Sandbox Code Playgroud)
从技术上讲,这不是您所要求的,但它是一种解决方法,可能会帮助需要类似行为的人。
并不真地。函数实际上有自己的作用域。默认情况下,在函数中分配的参数是全局的,但如果您显式声明它,则它具有本地范围:
foo() {
x=3 # global
declare y # local
...
}
Run Code Online (Sandbox Code Playgroud)
位置参数始终是函数的本地参数,因此您对它们进行的任何操作都只会在函数范围内生效。
从技术上讲,您始终可以使用递归来解决这个问题。如果您可以放心地再次调用原始脚本,则可以通过这种方式重新排序参数。例如
declare -i depth
outer() {
if (( depth++ < 1 )); then
outer "${@:4:$#}" "${@:1:3}"
return
fi
main "$@"
}
main() {
printf '%s\n' "$@"
}
outer "$@"
Run Code Online (Sandbox Code Playgroud)
对于我不理解的问题,这似乎是一个容易出错且令人困惑的解决方案,但它本质上是有效的。