循环遍历字符串列表
Posted
技术标签:
【中文标题】循环遍历字符串列表【英文标题】:Looping over a string list 【发布时间】:2014-09-19 02:50:07 【问题描述】:我想遍历以字符串形式给出的项目列表。根据 CMake 的要求,项目用分号分隔。以下
cmake_minimum_required(VERSION 2.8)
FOREACH(LETTER "a;b;c")
MESSAGE("<<$LETTER>>")
ENDFOREACH()
将字符串 "a;b;c"
解释为字符串文字。相反,当首先将"a;b;c"
分配给变量时,一切都按预期进行。
cmake_minimum_required(VERSION 2.8)
SET(MYLIST "a;b;c")
FOREACH(LETTER $MYLIST)
MESSAGE("<<$LETTER>>")
ENDFOREACH()
这是循环列表的推荐方式还是有更优雅的解决方案?
【问题讨论】:
【参考方案1】:您的困惑的根源可能是 CMake 对引用字符串的特殊解释。
例如,以下所有内容都正确地遍历了字符串列表:
(1) foreach(LETTER a b c) [...]
(2) foreach(LETTER a;b;c) [...]
(3) set(MYLIST "a;b;c")
foreach(LETTER $MYLIST) [...]
这不起作用的唯一情况是
(4) foreach(LETTER "a;b;c") [...]
(1)
和(2)
工作的原因在CMake's language manual for unquoted arguments中找到:
不带引号的参数内容由连续块中的所有文本组成 允许或转义的字符。转义序列和变量 参考文献被评估。结果值除以相同的 列表划分元素的方式。每个非空元素都被赋予 命令调用作为参数。因此,未引用的论点可能 以零个或多个参数的形式提供给命令调用。
请注意,这与quoted arguments 不同,后者也评估转义序列和变量引用,但不进行列表扩展。这就解释了为什么 (4)
会失败。
现在有趣的问题是为什么(3)
仍然成功。 set
将接受单值和列表值参数。事实上,关闭 )
或关键字 CACHE
或 PARENT_SCOPE
之前的所有内容都被视为值的一部分。因此,以下两个命令是等价的:
set(MYLIST "a;b;c")
set(MYLIST a;b;c)
在这两种情况下,MYLIST
的值都是a;b;c
(不带引号)。
当我们现在将$MYLIST
扩展为另一个命令时,您可以认为它使用MYLIST
的值执行简单的字符串替换,即a;b;c
。然后,生成的命令将通过引用或未引用参数的规则进行扩展。也就是说,以下将起作用:
foreach(LETTER $MYLIST) [...]
虽然这不会:
foreach(LETTER "$MYLIST") [...]
【讨论】:
【参考方案2】:首先,考虑是否在foreach
调用中键入所有值,例如foreach (N 1 2 3)
,或者如果您想扩展一个变量,例如foreach (N $MY_NUMBER_LIST)
。
虽然接受的答案扩展了该行上的变量,使代码注入成为可能(如果变量设置在您的脚本之外),它仍然适用于大多数情况。
但为了安全循环变量(不展开),请尝试以下操作:
# My dummy data.
set (_my_list "A B C")
string (REPLACE " " ";" _my_list "$_my_list")
# Actual looping.
foreach (my_entry IN LISTS _my_list)
# All done! do something with $my_entry, for example:
if (NOT my_entry IN_LIST _my_other_list)
message(FATAL_ERROR "_my_list has $my_entry but _my_other_list does not!!")
endif()
endforeach()
【讨论】:
以上是关于循环遍历字符串列表的主要内容,如果未能解决你的问题,请参考以下文章