我想创建一个BASH脚本,将另一个脚本或命令作为包装器调用。应该收集调用参数,但有一个例外。如何过滤特殊参数名称值对?
例如,当我用参数count X=$#
调用第一个脚本时:
$ ./foo.sh -v --first val1 ... --argname 'value with spaces' ... --last val3
然后它应该使用新的参数计数X'=X-2
调用第二个命令或脚本:
$ ./bar.sh -v --first val1 ... --last val3
可能有理由希望在函数中进行删除,但是您的尝试似乎过于复杂以及不安全和不透明,因为它不仅仅过滤数组。
args=("$@")
for ((i=0; i<"${#args[@]}"; ++i)); do
case ${args[i]} in
--argname) unset args[i]; unset args[i+1]; break;;
esac
done
./bar.sh "${args[@]}"
我为foo.sh
提出了这个解决方案:
#!/bin/bash
echo "executing foo.sh:"
function arg_remove ()
{
local array=("${@:3}")
for ((i=0; i<"${#array[@]}"; ++i)); do
case ${array[i]} in
"$2") unset array[i]; unset array[i+1]; break ;;
esac
done
# clean up unset array indexes
for i in "${!array[@]}"; do
new_array+=( "${array[i]}" )
done
array=("${new_array[@]}")
unset new_array
# assign array outside function scope
local -g "$1=( )"
eval ${1}='("${array[@]}")'
}
echo "arguments income :" "$@"
arg_remove ARG_PASS '--argname' "$@"
echo "arguments passed :" "${ARG_PASS[@]}"
./bar.sh "${ARG_PASS[@]}"
第二个输出测试脚本将只打印逐行bar.sh
分组的所有传递的参数:
#!/bin/bash
echo "executing bar.sh:"
while [[ $# -gt 0 ]]
do
key="$1"
if [[ "$key" == --* ]]; then
shift
echo $key $1
else
echo $key
fi
shift
done
现在调用第一个脚本会导致:
$ ./foo.sh -v --first val1 --argname 'value with spaces' --last val3
executing foo.sh:
arguments income : -v --first val1 --argname value with spaces --last val3
arguments passed : -v --first val1 --last val3
executing bar.sh:
-v
--first val1
--last val3
您还可以简化代码并删除function arg_remove
的分离并清理,这样您就可以获得foo_mini.sh
的简约版本而无需eval
:
#!/bin/bash
args=("${@}")
filter="--argname"
for ((i=0; i<"${#args[@]}"; ++i)); do
case ${args[i]} in
"$filter") unset args[i]; unset args[i+1]; break ;;
esac
done
./bar.sh "${args[@]}"