使用包含在双引号

时间:2017-07-26 22:19:39

标签: arrays bash cmake quotes

(这是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'

那没关系,但这似乎是一个黑客攻击。有更好的解决方案吗?

更新

如果你想迭代数组,你应该再使用一个变量(建议randomirJeff 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

2 个答案:

答案 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更好。