E.g:
set (txt "Hello" "There" "World")
# TODO
message (txt) # Prints "Hello\nThere\nWorld" (i.e. each list item on a new line
我应该代替TODO?
答案 0 :(得分:5)
CMake的列表以分号分隔。因此"Hello" "There" "World"
在内部表示为Hello;There;World
。因此,一个简单的解决方案是用换行符替换分号:
string (REPLACE ";" "\n" txt "${txt}")
这适用于此示例,但是让我们尝试一个更复杂的示例:
set (txt "" [[\;One]] "Two" [[Thre\;eee]] [[Four\\;rrr]])
[[
]]
是一个原始字符串,因此\
将被传递到列表的CMake内部表示中不变。内部表示为:;\;One;Two;Thre\;eee;Four\\;rrr
。我们希望它能打印出来:
<blank line>
;One
Two
Thre;eee
Four\\;rrr
我实际上并非100%确定Four\\;rrr
,但我认为这是正确的。无论如何,我们实际上得到了这个:
<blank line>
\
One
Two
Thre\
eee
Four\\
rrr
这是因为它不知道不转换转义的实际分号。解决方案是使用正则表达式:
string (REGEX REPLACE "[^\\\\];" "\\1\n" txt "${txt}")
即。如果前面有非;
字符(并将该字符放在替换中),则仅替换\
。 几乎有效,但它不处理第一个空元素,因为分号前面没有任何内容。最后的答案是允许字符串的开始:
string (REGEX REPLACE "(^|[^\\\\]);" "\\1\n" txt "${txt}")
哦,\\\\
是因为CMake处理字符串文字而另一个级别的转义被正则表达式引擎删除。你也可以这样做:
string (REGEX REPLACE [[(^|[^\\]);]] "\\1\n" txt "${txt}")
但我不认为这更清楚。
也许有一种比这更简单的方法,但我无法找到它。无论如何,女士们,先生们,为什么你不应该使用字符串作为你唯一的类型,或者做带内字符串分隔。不过,可能会更糟 - 至少他们没有像Bash那样使用空格作为分隔符!
答案 1 :(得分:2)
我只是想添加一些替代方案,我只是使用message()
确实在最后放置换行的事实:
只需使用for_each()
迭代列表:
set (txt "Hello" "There" "World")
foreach(line IN LISTS txt)
message("${line}")
endforeach()
基于function()
的替代方案,我提出看起来更复杂:
function(message_cr line)
message("${line}")
if (ARGN)
message_cr(${ARGN})
endif()
endfunction()
set(txt "Hello" "There" "World")
message_cr(${txt})
这些方法的更通用版本如下:
for_each()
字符串
set(txt "Hello" "There" "World")
foreach(line IN LISTS txt)
string(APPEND multiline "${line}\n")
endforeach()
message("${multiline}")
function()
字符串
function(stringify_cr var line)
if (ARGN)
stringify_cr(${var} ${ARGN})
endif()
set(${var} "${line}\n${${var}}" PARENT_SCOPE)
endfunction()
set(txt "Hello" "There" "World")
stringify_cr(multiline ${txt})
message(${multiline})
如果您不喜欢最后添加的换行符,请添加string(STRIP "${multiline}" multiline)
。