在bash脚本中调用带有变量空格的命令行

时间:2011-04-20 13:12:33

标签: bash

我觉得这很容易,但我已经浪费了几个小时了。

我想从bash脚本中运行以下cmake命令。在终端我输入

cmake -G "Unix Makefiles" .

它有效。如果我将其完全复制到bash脚本中,它也能正常工作。

但该脚本适用于多个平台,可能是“MSYS Makefiles”而不是“Unix Makefiles”。因此,我想将命令放在一个变量中,其中的内容取决于平台并执行它。然而,这是我被卡住的地方。我尝试了我能想到的单/双引号的每一个组合,但无处可去。

我想要的是一线

c="cmake . -G \"Unix Makefiles\""
exec $c

但它总会导致以下一些变化:

CMake Error: Could not create named generator "Unix

我意识到我能做到

if test [... this is unix ...]
    cmake . -G "Unix Makefiles"
else
    cmake . -G "MSYS Makefiles
fi

但是由于这个电话必须要多次,我宁愿避免它。

有什么建议吗?

5 个答案:

答案 0 :(得分:5)

最好不要不必要地使用eval。尽量不要将命令放在变量中。 您可以通过

将选项作为变量
if [ ... ]
  string="Unix makefiles"
else
  string="MSYS Makefiles"
else
  string="...."
fi
cmake -G "$string" #just call the command normally

答案 1 :(得分:3)

救援的Bash FAQ:引号是语法的(意思是引号不是名称的一部分),所以你应该得到预期的结果:

if test [.... this is unix ...]
    target="Unix Makefiles"
else
    target="MSYS Makefiles"
fi
cmake . -G "$target"

PS:eval is evil

答案 2 :(得分:2)

使用eval告诉shell重新解析命令行:

c="cmake . -G \"Unix Makefiles\""
eval "$c"

或者,我喜欢使用数组来避免不必要的反斜杠和eval

# Store command in 4-element array: ["cmake", ".", "-G", "Unix Makefiles"].
# No backslash escapes needed.
c=(cmake . -G "Unix Makefiles")

# Ugly syntax for expanding out each element of an array, with all the spaces and
# quoting preserved to ensure that "Unix Makefiles" remains a single word.
"${c[@]}"

答案 3 :(得分:0)

在字符串上调用exec,实际上最终会使用以下参数执行cmake

1: .
2: -G
3: "Unix
4: Makefiles"

exec本身不解释引号,只是空格,并以这种方式将参数传递给execve系统调用。你需要让bash使用像eval这样的内置来解释引号。

答案 4 :(得分:0)

您也可以使用... | xargs bash -c '...'将字符串重新分析为命令行参数。 (但是,使用xargs可能不是多平台的理想解决方案。)

# example: find file names with a space
c=". -maxdepth 3 -name \"* *\""
printf '%s' "$c" | xargs bash -c 'set -xv; find "$@"' arg0 2>&1| less

另一种选择是使用像shebang.c这样的shebang助手!

http://semicomplete.googlecode.com/svn/codesamples/shebang.c