将shell转义的参数字符串传递给Bourne shell中的子命令

adr*_*ian 4 shell quotes arguments escaping sh

假设我有一个命令我想运行(cmd)和一个包含我想要传递给函数的参数的变量(类似的东西--foo 'bar baz' qux).像这样:

#!/bin/sh
command=cmd
args="--foo 'bar baz' qux"
Run Code Online (Sandbox Code Playgroud)

参数包含引号,如上所示,它们将包含空格的参数组合在一起.然后我想运行命令:

$command $args
Run Code Online (Sandbox Code Playgroud)

这当然,导致与运行命令4个参数:--foo,'bar,baz',和qux.我习惯的替代方案(即使用时"$@")会出现另一个问题:

$command "$args"
Run Code Online (Sandbox Code Playgroud)

这将使用一个参数执行命令:--foo 'bar baz' qux.

我怎样才能运行该命令与3个参数(--foo,bar baz,和qux)如预期?

Cha*_*ffy 8

使用数组来准确指定你的参数列表,没有字符串拆分(这就是在这里做错了什么)妨碍你:

args=( --foo "bar baz" qux )
command "${args[@]}"
Run Code Online (Sandbox Code Playgroud)

如果需要动态构建参数列表,可以使用以下命令追加到数组+=:

args=( )
while ...; do
   args+=( "$another_argument" )
done
call_your_subprocess "${args[@]}"
Run Code Online (Sandbox Code Playgroud)

请注意,使用引号[@]代替[*],是必不可少的.

  • OP询问Bourne Shell(即`/ bin/sh`).这对于`bash`来说是一个很好的解决方案,但我不相信bourne shell支持数组,是吗? (3认同)

l0b*_*0b0 5

如果你可以扔掉当前的位置变量($1...),你可以使用以下内容:

set -- '--foo' 'bar baz' 'qux'
echo "$#" # Prints "3" (without quotes)
echo "$2" # Prints "bar baz" (without quotes)
command "$@"
Run Code Online (Sandbox Code Playgroud)

只是在#!/usr/bin/env sh脚本中测试它,所以它至少在Dash中起作用,并且应该适用于任何Bourne Shell变体.不eval,Python或Bash必要.