【问题标题】: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()

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

【问题讨论】:

    标签: list foreach cmake


    【解决方案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()
      

      【讨论】:

        猜你喜欢
        • 2023-01-24
        • 2021-04-02
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 2015-01-04
        • 2020-06-19
        • 2023-03-23
        相关资源
        最近更新 更多