使用数组中的参数调用程序,该数组包含用双引号括起来的另一个数组中的项

call program with arguments from an array containing items from another array wrapped in double quotes

提问人:bibermann 提问时间:7/27/2017 最后编辑:bibermann 更新时间:7/27/2017 访问量:190

问:

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

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

更新

如果你想遍历数组,你应该再使用一个变量(正如 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-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"
Arrays bash CMake 行情

评论


答:

1赞 randomir 7/27/2017 #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

如果您需要以可以通过复制/粘贴重用的方式打印带有参数的完整命令,您可以考虑使用 with format 说明符,它将以可重用作 shell 输入的方式引用参数printf%q

$ printf "cmake .. "; printf "%q " "${cmake_arguments[@]}"; printf "\n"
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-fdiagnostics-color\ -O3

请注意转义空格的反斜杠。

评论

0赞 bibermann 7/27/2017
这有效,但后来打印错误:(似乎 -O3 是 cmake 的一个参数,它不可复制粘贴)-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-fdiagnostics-color -O3
0赞 randomir 7/27/2017
对不起,我不明白是什么困扰着你。这样写的时候会编译吗?您还想让它打印可复制粘贴的输出吗?用于什么目的?如果您提供足够的详细信息,我们将解决此问题。:)
1赞 bibermann 7/27/2017
是的,但是在我的问题中,我写了它应该打印得很漂亮,我举了一个例子:)输出用作人类的构建指令。
0赞 randomir 7/27/2017
好的,那么,你想编译和打印它以便在 shell 中重用吗?看看我的更新,有帮助吗?
0赞 bibermann 7/29/2017
这在技术上很有趣,但不如 ,例如,人们不认为 -O3 属于标志。除了美学上的缺点之外,如果有人想从 cmd 行中复制或粘贴一些参数,这是不切实际的。这不是你写这种东西的方式:/但无论如何,谢谢!-DCMAKE_CXX_FLAGS="-fdiagnostics-color -O3"
1赞 Jeff Breadner 7/27/2017 #2

似乎在 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

评论

0赞 bibermann 7/27/2017
看起来没问题,但随后 g++ 抱怨:g++: error: unrecognized command line option ‘-fdiagnostics-color -O3’
0赞 Jeff Breadner 7/27/2017
也许再次使用相同的技巧,请参阅我的编辑(添加CMAKE_ARGUMENTS变量以解析数组)
0赞 bibermann 7/27/2017
然后 CMake 认为是一个参数,但这是两个参数。如果我在调用中省略双引号,则标志将解析为-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-fdiagnostics-color -O3"'-DCMAKE_CXX_FLAGS="-fdiagnostics-color' '-O3"'
0赞 Jeff Breadner 7/27/2017
我移动了一些引号,但这看起来与@randomir提供的答案非常相似,但被拒绝了。
0赞 bibermann 7/27/2017
问题仍然存在(CMake 的单个参数)。