例如:
set (txt "Hello" "There" "World") # TODO message (txt) # Prints "Hello\nThere\nWorld" (i.e. each list item on a new line
我要用什么代替TODO?
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
。我们希望它能打印:
;One Two Thre;eee Four\\;rrr
我实际上并不确定100%,Four\\;rrr
但是我认为这是正确的。无论如何,通过天真的实现,我们实际上得到了以下信息:
\ 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那样使用空格作为分隔符!