我正在尝试编写一个bash脚本,它接受一个环境变量并将其传递给一个命令。
所以,如果我有类似的东西:
export OUT="-a=arg1 -b=\"arg2.0 arg2.1\""
我希望在我的bash脚本中执行以下操作:
<command> -a=arg1 '-b=arg2.0 arg2.1'
我有一种似乎这样做的方法,但它涉及使用eval:
eval <command> ${OUT}
如果我对命令包含set -x
,我会看到:
+ eval <command> a=arg1 'b="arg2.0' 'arg2.1"'
++ <command> -a=arg1 '-b=arg2.0 arg.1'
然而,我已经探讨了使用eval的危险,因为这将从用户输入中获取参数,这不太理想。
由于这是bash,我还考虑使用数组来存储我的参数,并简单地放置:<command> "$ARRAY[@]"
来做我想要的。我一直在尝试使用IFS,但我不确定我应该分开什么。
答案 0 :(得分:2)
对于上述答案中描述的简化问题;即,将以下环境变量转换为bash脚本中的三个参数:
export OPTS="a=arg1 b=arg2.0 b=arg2.1"
请执行以下操作:
#!/bin/bash
opts=( $OPTS )
my-command "${opts[@]}"
# Use this for debugging:
echo "number of opts = ${#opts[@]}; opts are: ${opts[@]}"
答案 1 :(得分:1)
如果您对$OUT
的格式不完全不灵活,可能会重复option=
字符串以允许连接。然后你会写:
export OUT="a=arg1 b=arg2.0 b=arg2.1"
如果可以接受,则以下脚本将起作用
#!/bin/bash
# Parse $OUT into an associative array.
# Instead of using $OUT, it would be cleaner to use "$@".
declare -A args
for arg in $OUT; do
if [[ "$arg" =~ ^([[:alnum:]]+)=(.*)$ ]]; then
key=${BASH_REMATCH[1]}
val=${BASH_REMATCH[2]}
if [[ -z ${args[$key]} ]]; then
args[$key]=-$key="$val"
else
args[$key]+=" $val"
fi
fi
done
# Test, approximately as specified
command() { :; }
set -x
command "${args[@]}"
set +x
我不能说我喜欢它,但它是我能够来的最接近的。
这是一个示例运行:
$ export OUT="a=foo b=bar b=glitch s9= s9=* "
./command-runner
+ command -a=foo '-b=bar glitch' '-s9= *'
+ :
+ set +x
如果导入bash函数(例如,在bash启动文件中),则可以更好地使用数组。这是一种方法:
# This goes into your bash startup file:
declare -a SAVED_ARGS
save_args() {
SAVED_ARGS=("$@")
}
do_script() {
/path/to/script.sh "${SAVED_ARGS[@]}" "$@"
}
出于说明目的,script.sh
:
#!/bin/bash
command() { :; }
set -x
command "${@/#/-}"
set +x
示例:
$ save_args x=3 y="a few words from our sponsor"
$ do_script a=3 b="arg2.0 arg2.1"
+ command -x=3 '-y=a few words from our sponsor' -a=3 '-b=arg2.0 arg2.1'
+ :
+ set +x
$ do_script a=42
+ command -x=3 '-y=a few words from our sponsor' -a=42
+ :
+ set +x
如果不明显:
command() { :; }
定义了一个名为command
的bash函数,它几乎不执行任何操作(除了调用内置:
之外什么也没做),并且
"${@/#/-}"
扩展到位置参数,在每个开头插入一个破折号使用查找和替换替换。模式#
实际上是一个空模式,只匹配字符串的开头。