2011-08-24 11 views
12

में किसी सूची में शामिल होने का सबसे अच्छा/सबसे छोटा तरीका सीएमके में एक स्ट्रिंग में सूची में शामिल होने का सबसे अच्छा तरीका क्या है?सीएमके

शामिल होने से मेरा मतलब है एसईटी (somelist "a" "b" "c \; c") "ए: बी: सी; सी" में परिवर्तित करें जहां गोंद स्ट्रिंग (":") चुनने योग्य है। निम्नलिखित कोड काम करता है लेकिन यह वास्तव में लंबा है, क्या कोई बेहतर तरीका है?

FUNCTION(JOIN LISTNAME GLUE OUTPUT) 
SET(_TMP_STR "") 
    FOREACH(VAL ${${LISTNAME}}) 
    SET(_TMP_STR "${_TMP_STR}${GLUE}${VAL}") 
    ENDFOREACH(VAL ${${LISTNAME}}) 
    STRING(LENGTH "${GLUE}" GLUE_LEN) 
    STRING(LENGTH "${_TMP_STR}" OUT_LEN) 
    MATH(EXPR OUT_LEN ${OUT_LEN}-${GLUE_LEN}) 
    STRING(SUBSTRING "${_TMP_STR}" ${GLUE_LEN} ${OUT_LEN} _TMP_STR) 
    SET(${OUTPUT} "${_TMP_STR}" PARENT_SCOPE) 
ENDFUNCTION() 

#USAGE: 
SET(somelist "a" "b" "c\;c") 
JOIN(somelist ":" output) 
MESSAGE("${output}") # will output "a:b:c;c" 

दुर्भाग्य से STRING (बदलें ...) का उपयोग कर काम नहीं करता:

function(JOIN VALUES GLUE OUTPUT) 
    string (REPLACE ";" "${GLUE}" _TMP_STR "${VALUES}") 
    set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE) 
endfunction() 

#USAGE: 
SET(somelist a b c) 
JOIN("${somelist}" ":" output) 
MESSAGE("${output}") # will output "a:b:c" 

उत्तर

10

आमतौर पर इस कार्य को सरल string REPLACE कमांड के साथ हल किया जाता है:

function(JOINSTRREPLACE VALUES GLUE OUTPUT) 
    string (REPLACE ";" "${GLUE}" _TMP_STR "${VALUES}") 
    set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE) 
endfunction() 
JOINSTRREPLACE("${somelist}" ":" output) 
MESSAGE(${output}) # will output "a:b:c\:c" 
6

आप string REPLACE समारोह का उपयोग कर सकते । आप cmake के साथ आने वाली स्क्रिप्ट में ऐसी कई प्रतिस्थापन पा सकते हैं।

function(JOIN VALUES GLUE OUTPUT) 
    string (REGEX REPLACE "([^\\]|^);" "\\1${GLUE}" _TMP_STR "${VALUES}") 
    string (REGEX REPLACE "[\\](.)" "\\1" _TMP_STR "${_TMP_STR}") #fixes escaping 
    set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE) 
endfunction() 

SET(letters "" "\;a" b c "d\;d") 
JOIN("${letters}" ":" output) 
MESSAGE("${output}") # :;a:b:c:d;d 
+0

अरे हाँ धन्यवाद, इस काम करता है। लेकिन क्या इसका मतलब यह है कि मेरे पास ऐसी सूची नहीं हो सकती है जहां एक तत्व में अर्धविराम होता है? – Geli

+1

मैंने अर्धविराम वाले तत्वों के साथ एक सूची शामिल करने के लिए प्रश्न को अद्यतन किया। – Geli

+0

आपका मूल कार्य जॉइन अर्धविराम से निपटता नहीं है। यह सेमीकेक 2.8.5 के साथ विंडोज के तहत "ए: बी: सीसी" आउटपुट करता है। – sakra

5

जवाब ऊपर ठीक कर रहे हैं, आप अर्धविराम का उपयोग नहीं करते जब या जब आप कर सकते हैं (और करना चाहते हैं) से बच: यदि आपको वास्तव में आप मूल्यों के अंदर अर्धविराम के बारे में परवाह करने की जरूरत है, तो आप निम्नलिखित कोड का उपयोग कर सकते उन्हें। मैं अर्धविराम से बचने के लिए नहीं पसंद करते हैं, तो मैं निम्नलिखित समारोह लिखा है:

function(JOIN OUTPUT GLUE) 
    set(_TMP_RESULT "") 
    set(_GLUE "") # effective glue is empty at the beginning 
    foreach(arg ${ARGN}) 
     set(_TMP_RESULT "${_TMP_RESULT}${_GLUE}${arg}") 
     set(_GLUE "${GLUE}") 
    endforeach() 
    set(${OUTPUT} "${_TMP_RESULT}" PARENT_SCOPE) 
endfunction() 

लाभ यह है कि सूची खाली हो सकता है और यह एक चर में होने की जरूरत नहीं है (लेकिन जगह में लिखा जा सकता है आमंत्रण का)।

उपयोग है:

set(SOME_LIST a b c d) 
join(RESULT "/" ${SOME_LIST}) 
message(STATUS "RESULT='${RESULT}'") # outputs RESULT='a/b/c/d' 
# or 
join(RESULT " " e f g h) 
message(STATUS "RESULT='${RESULT}'") # outputs RESULT='e f g h'