提问人:bibermann 提问时间:7/27/2017 最后编辑:bibermann 更新时间:7/27/2017 访问量:190
使用数组中的参数调用程序,该数组包含用双引号括起来的另一个数组中的项
call program with arguments from an array containing items from another array wrapped in double quotes
问:
(这是bash中讨论的问题的更具体版本 - 从包含双引号的数组中扩展参数。
我希望 bash 使用带有双引号的数组中的参数调用 cmake,该数组本身包含来自另一个数组的项目。下面是一个示例,用于说明:
cxx_flags=()
cxx_flags+=(-fdiagnostics-color)
cxx_flags+=(-O3)
cmake_arguments=()
cmake_arguments+=(-DCMAKE_BUILD_TYPE=Release)
cmake_arguments+=("-DCMAKE_CXX_FLAGS=\"${cxx_flags[@]}\"")
参数应打印如下:
$ echo "CMake arguments: ${cmake_arguments[@]}"
CMake arguments: -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-fdiagnostics-color -O3"
问题
最后应该调用 cmake(这不起作用!
cmake .. "${cmake_arguments[@]}"
它扩展为(正如 set -x
生成的那样):
cmake .. -DCMAKE_BUILD_TYPE=Release '-DCMAKE_CXX_FLAGS="-fdiagnostics-color' '-O3"'
解决方法
echo "cmake .. ${cmake_arguments[@]}" | source /dev/stdin
扩展为:
cmake .. -DCMAKE_BUILD_TYPE=Release '-DCMAKE_CXX_FLAGS=-fdiagnostics-color -O3'
没关系,但这似乎是一个黑客。有更好的解决方案吗?
更新
如果你想遍历数组,你应该再使用一个变量(正如 randomir 和 Jeff Breadner 建议的那样):
cxx_flags=()
cxx_flags+=(-fdiagnostics-color)
cxx_flags+=(-O3)
cxx_flags_string="${cxx_flags[@]}"
cmake_arguments=()
cmake_arguments+=(-DCMAKE_BUILD_TYPE=Release)
cmake_arguments+=("-DCMAKE_CXX_FLAGS=\"$cxx_flags_string\"")
核心问题仍然存在(并且解决方法仍然有效),但您可以遍历并查看两个项目(按预期)而不是三个(和):cmake_arguments
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_CXX_FLAGS="-fdiagnostics-color
-O3"
echo "cmake .. \\"
size=${#cmake_arguments[@]}
for ((i = 0; i < $size; ++i)); do
if [[ $(($i + 1)) -eq $size ]]; then
echo " ${cmake_arguments[$i]}"
else
echo " ${cmake_arguments[$i]} \\"
fi
done
指纹:
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-fdiagnostics-color -O3"
答:
你基本上希望数组扩展为一个单词。cxx_flags
这:
cxx_flags=()
cxx_flags+=(-fdiagnostics-color)
cxx_flags+=(-O3)
flags="${cxx_flags[@]}"
cmake_arguments=()
cmake_arguments+=(-DCMAKE_BUILD_TYPE=Release)
cmake_arguments+=(-DCMAKE_CXX_FLAGS="$flags")
将产生您想要的输出:
$ set -x
$ echo "${cmake_arguments[@]}"
+ echo -DCMAKE_BUILD_TYPE=Release '-DCMAKE_CXX_FLAGS=-fdiagnostics-color -O3'
所以,总结一下,运行:
cmake .. "${cmake_arguments[@]}"
使用数组扩展引号时,确保每个数组元素(cmake 参数)仅扩展为一个单词(如果它包含空格,shell 不会在其周围打印引号,但执行的命令将接收整个字符串作为单个参数)。您可以使用 验证这一点。set -x
如果您需要以可以通过复制/粘贴重用的方式打印带有参数的完整命令,您可以考虑使用 with format 说明符,它将以可重用作 shell 输入的方式引用参数:printf
%q
$ printf "cmake .. "; printf "%q " "${cmake_arguments[@]}"; printf "\n"
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-fdiagnostics-color\ -O3
请注意转义空格的反斜杠。
评论
-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-fdiagnostics-color -O3
-DCMAKE_CXX_FLAGS="-fdiagnostics-color -O3"
似乎在 cmake 满意之前必须进行另一层解析;处理此问题,但您也可以通过其他变量移动 CXX 标志:| source /dev/stdin
#!/bin/bash -x
cxx_flags=()
cxx_flags+=(-fdiagnostics-color)
cxx_flags+=(-O3)
CXX_FLAGS="${cxx_flags[@]}"
cmake_arguments=()
cmake_arguments+=(-DCMAKE_BUILD_TYPE=Release)
cmake_arguments+=("'-DCMAKE_CXX_FLAGS=${CXX_FLAGS}'")
CMAKE_ARGUMENTS="${cmake_arguments[@]}"
echo "CMake arguments: ${CMAKE_ARGUMENTS}"
返回:
+ cxx_flags=()
+ cxx_flags+=(-fdiagnostics-color)
+ cxx_flags+=(-O3)
+ CXX_FLAGS='-fdiagnostics-color -O3'
+ cmake_arguments=()
+ cmake_arguments+=(-DCMAKE_BUILD_TYPE=Release)
+ cmake_arguments+=("'-DCMAKE_CXX_FLAGS=${CXX_FLAGS}'")
+ CMAKE_ARGUMENTS='-DCMAKE_BUILD_TYPE=Release '\''-DCMAKE_CXX_FLAGS=-fdiagnostics-color -O3'\'''
+ echo 'CMake arguments: -DCMAKE_BUILD_TYPE=Release '\''-DCMAKE_CXX_FLAGS=-fdiagnostics-color -O3'\'''
CMake arguments: -DCMAKE_BUILD_TYPE=Release '-DCMAKE_CXX_FLAGS=-fdiagnostics-color -O3'
可能还有更干净的解决方案,但我认为这比事情要好。| source /dev/stdin
评论
g++: error: unrecognized command line option ‘-fdiagnostics-color -O3’
-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-fdiagnostics-color -O3"
'-DCMAKE_CXX_FLAGS="-fdiagnostics-color' '-O3"'
评论