循环遍历字符串列表

Nic*_*mer 22 foreach list cmake

我想循环遍历字符串中给出的项目列表.根据CMake的要求,项目以分号分隔.下列

cmake_minimum_required(VERSION 2.8)

FOREACH(LETTER "a;b;c")
  MESSAGE("<<${LETTER}>>")
ENDFOREACH()
Run Code Online (Sandbox Code Playgroud)

将字符串解释"a;b;c"为字符串文字.相反,当首先分配"a;b;c"变量时,所有变量都按预期进行.

cmake_minimum_required(VERSION 2.8)

SET(MYLIST "a;b;c")
FOREACH(LETTER ${MYLIST})
  MESSAGE("<<${LETTER}>>")
ENDFOREACH()
Run Code Online (Sandbox Code Playgroud)

这是循环列表的推荐方法还是有更优雅的解决方案?

Com*_*sMS 38

你混淆的根源可能是CMake对引用字符串的特殊解释.

例如,以下所有内容都正确迭代字符串列表:

(1) foreach(LETTER a b c) [...]
(2) foreach(LETTER a;b;c) [...]
(3) set(MYLIST "a;b;c")
    foreach(LETTER ${MYLIST}) [...]
Run Code Online (Sandbox Code Playgroud)

这不起作用的唯一情况是

(4) foreach(LETTER "a;b;c") [...]
Run Code Online (Sandbox Code Playgroud)

为什么(1)(2)工作在CMake的语言手册中找到了不带引号的参数:

不带引号的参数内容由连续的允许或转义字符块中的所有文本组成.评估转义序列和变量引用.结果值的分割方式与Lists分为元素的方式相同.每个非空元素都作为参数提供给命令调用.因此,可以将命令调用的不带引号的参数赋予零个或多个参数.

请注意,这与引用的参数不同,引用的参数也评估转义序列和变量引用,但不进行列表扩展.这解释了为什么(4)失败.

现在有趣的问题是为什么(3)仍然成功.set将接受单值和列表值参数.事实上,关闭前的所有内容)或其中一个关键字CACHE或被PARENT_SCOPE视为价值的一部分.因此,以下两个命令是等效的:

set(MYLIST "a;b;c")
set(MYLIST a;b;c)
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,值MYLIST都是a;b;c(没有引号).

当我们现在扩展${MYLIST}到另一个命令时,你可以认为它执行一个简单的字符串替换MYLIST,其值为a;b;c.然后,生成的命令将通过引用或不引用参数的规则进行扩展.也就是说,以下内容将起作用:

foreach(LETTER ${MYLIST}) [...]
Run Code Online (Sandbox Code Playgroud)

虽然这不会:

foreach(LETTER "${MYLIST}") [...]
Run Code Online (Sandbox Code Playgroud)