循环遍历字符串列表

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 将接受单值和列表值参数。事实上,关闭 ) 或关键字 CACHEPARENT_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()

【讨论】:

以上是关于循环遍历字符串列表的主要内容,如果未能解决你的问题,请参考以下文章

C#循环遍历列表以查找字符数

循环遍历列表中的字符串

动态循环遍历Python函数中的函数列表

Python3基础 for循环 遍历并输出一个字符串的列表

ast.literal_eval - 循环遍历列表中的字符串元素

在不使用 ForEach 循环的情况下遍历列表