bash 使用环境变量将参数传递给命令

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23924181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:33:52  来源:igfitidea点击:

Using an environment variable to pass arguments to a command

basheval

提问by Ed Y

I'm trying to write a bash script that takes an environment variable and passes it along to a command.

我正在尝试编写一个 bash 脚本,它接受一个环境变量并将其传递给一个命令。

So if I had something like:

所以如果我有类似的东西:

export OUT="-a=arg1 -b=\"arg2.0 arg2.1\""

I want in my bash script to do something like:

我希望在我的 bash 脚本中执行以下操作:

<command> -a=arg1 '-b=arg2.0 arg2.1'

I have one approach that seems to do this, but it involves using eval:

我有一种方法似乎可以做到这一点,但它涉及使用 eval:

eval <command> ${OUT}

If I include set -xright about the command, I will see:

如果我包含set -x正确的命令,我会看到:

+ eval <command> a=arg1 'b="arg2.0' 'arg2.1"'
++ <command> -a=arg1 '-b=arg2.0 arg.1'

However, I've poked around the dangers of using eval and since this will be taking the arguments from user input, it's less than ideal.

但是,我已经探讨了使用 eval 的危险,并且由于这将从用户输入中获取参数,因此不太理想。

Since this is bash, I've also considered using arrays to store my arguments and simply put: <command> "$ARRAY[@]"to do what I want. I've been trying to use IFS, but I'm not sure what I should be splitting on.

由于这是 bash,我还考虑使用数组来存储我的参数并简单地说:<command> "$ARRAY[@]"做我想做的事。我一直在尝试使用 IFS,但我不确定我应该拆分什么。

采纳答案by rici

If you're not completely inflexible about the format of $OUT, one possibility would be to repeat the option=string to allow for concatenation. Then you'd write:

如果您对 的格式不是完全不灵活$OUT,一种可能性是重复option=字符串以允许连接。然后你会写:

export OUT="a=arg1 b=arg2.0 b=arg2.1"

If that is acceptable, the following script will work

如果这是可以接受的,以下脚本将起作用

#!/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

I can't say I like it much, but it's the closest I've been able to come.

我不能说我很喜欢它,但这是我能来的最接近的。

Here's a sample run:

这是一个示例运行:

$ export OUT="a=foo b=bar  b=glitch s9= s9=* "
./command-runner
+ command -a=foo '-b=bar glitch' '-s9= *'
+ :
+ set +x


If you import a bash function (for example, in your bash startup file), you can make much better use of arrays. Here's one approach:

如果您导入一个 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[@]}" "$@"
}

For expository purposes, script.sh:

出于说明目的,script.sh

#!/bin/bash
command() { :; }

set -x
command "${@/#/-}"
set +x

Example:

例子:

$ 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

In case it's not obvious:

如果不明显:

command() { :; }

defines a bash function called commandwhich does almost nothing (except invoke the builtin :which does nothing), and

定义了一个command几乎什么都不做的 bash 函数(除了调用:什么都不做的内置函数),和

"${@/#/-}"

expands to the positional parameters, inserting a dash at the beginning of each one use a find-and-replace substitution. The pattern #is actually an empty pattern which only matches at the beginning of the string.

扩展到位置参数,在每个参数的开头插入一个破折号,使用查找和替换替换。模式#实际上是一个空模式,只匹配字符串的开头。

回答by Klortho

For the simplified problem described in the answer above; i.e., turning the following environment variable into three arguments inside a bash script:

对于上述答案中描述的简化问题;即,将以下环境变量转换为 bash 脚本中的三个参数:

export OPTS="a=arg1 b=arg2.0 b=arg2.1"

Just do the following:

只需执行以下操作:

#!/bin/bash
opts=( $OPTS )
my-command "${opts[@]}"

# Use this for debugging:
echo "number of opts = ${#opts[@]}; opts are: ${opts[@]}"