(这是bash - expand arguments from array containing double quotes 中讨论的问题的更具体版本。)
我希望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(不工作!):</ p>
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
和{{ 1}}):
-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
答案 0 :(得分:1)
您基本上希望将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
验证该内容。
如果您需要以可以通过复制/粘贴重用的方式打印包含参数的完整命令,您可以考虑将printf
与%q
格式说明符一起使用,这将引用以一种可以作为shell输入重用的方式的参数:
$ printf "cmake .. "; printf "%q " "${cmake_arguments[@]}"; printf "\n"
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-fdiagnostics-color\ -O3
注意逃避空间的反斜杠。
答案 1 :(得分:1)
似乎在cmake开心之前还有另一层解析; | source /dev/stdin
处理此问题,但您也可以通过其他变量移动CXX标记:
#!/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
更好。