CMake中的string命令用于字符串操作,其格式如下:
Search and Replace
string(FIND <string> <substring> <out-var> [...])
string(REPLACE <match-string> <replace-string> <out-var> <input>...)
string(REGEX MATCH <match-regex> <out-var> <input>...)
string(REGEX MATCHALL <match-regex> <out-var> <input>...)
string(REGEX REPLACE <match-regex> <replace-expr> <out-var> <input>...)
Manipulation
string(APPEND <string-var> [<input>...])
string(PREPEND <string-var> [<input>...])
string(CONCAT <out-var> [<input>...])
string(JOIN <glue> <out-var> [<input>...])
string(TOLOWER <string> <out-var>)
string(TOUPPER <string> <out-var>)
string(LENGTH <string> <out-var>)
string(SUBSTRING <string> <begin> <length> <out-var>)
string(STRIP <string> <out-var>)
string(GENEX_STRIP <string> <out-var>)
string(REPEAT <string> <count> <out-var>)
Comparison
string(COMPARE <op> <string1> <string2> <out-var>)
Hashing
string(<HASH> <out-var> <input>)
Generation
string(ASCII <number>... <out-var>)
string(HEX <string> <out-var>)
string(CONFIGURE <string> <out-var> [...])
string(MAKE_C_IDENTIFIER <string> <out-var>)
string(RANDOM [<option>...] <out-var>)
string(TIMESTAMP <out-var> [<format string>] [UTC])
string(UUID <out-var> ...)
JSON
string(JSON <out-var> [ERROR_VARIABLE <error-var>]
{GET | TYPE | LENGTH | REMOVE}
<json-string> <member|index> [<member|index> ...])
string(JSON <out-var> [ERROR_VARIABLE <error-var>]
MEMBER <json-string>
[<member|index> ...] <index>)
string(JSON <out-var> [ERROR_VARIABLE <error-var>]
SET <json-string>
<member|index> [<member|index> ...] <value>)
string(JSON <out-var> [ERROR_VARIABLE <error-var>]
EQUAL <json-string1> <json-string2>)
1.Search and Replace:
(1).FIND:在提供的<string>中查找给定的<substring>,若找到则返回其位置;如果使用了REVERSE标志,该命令将搜索<substring>在<string>中最后出现的位置;若未找到则返回-1。string(FIND)子命令将所有字符串视为纯ASCII字符。变量<out-var>中存储的索引也会以字节为单位计算,因此包含多字节字符的字符串(strings containing multi-byte characters)可能会导致意外结果(unexpected results)。
set(str beijing//beijing//beijing)
string(FIND ${str} "jing" var)
message("var: ${var}") # var: 3
string(FIND ${str} "jing" var REVERSE)
message("var: ${var}") # var: 21
string(FIND ${str} "\\" var)
message("var: ${var}") # var: -1
(2).REPLACE:将<input>中所有出现的<match_string>替换为<replace_string>,并将结果存储在<out-var>中。若<match_string>在<input>中未出现,<out-var>的值将为<input>。
set(str https://blog.csdn.net/fengbingchun)
string(REPLACE "blog.csdn.net" "github.com" var ${str})
message("var: ${var}") # var: https://github.com/fengbingchun
string(REPLACE "xxxx" "yyyy" var ${str})
message("var: ${var}") # var: https://blog.csdn.net/fengbingchun
(3).CMake中的正则表达式(Regular Expression):以下字符在正则表达式中具有特殊含义
^:匹配输入字符串的开始位置;
$:匹配输入字符串结尾的位置;
.:匹配任何单个字符;
\<char>:匹配<char>指定的单个字符。使用它来匹配特殊的正则表达式字符。将下一个字符标记为特殊字符。转义非特殊字符(non-special character)是不必要但允许的,例如\a匹配a;
[]:匹配括号内的任何字符;
[^]:匹配不在括号内的任何字符;
-:在括号内,指定两边字符之间的包含范围;
*:零次或多次匹配前面的字符;
+:一次或多次匹配前面的字符;
?:零次或一次匹配前面的字符;
|:匹配"|"两边的字符;
():保存匹配的子表达式;
*、+和?具有比串联(concatenation)更高的优先级。|的优先级低于concatenation。这意味着正则表达式^ab+d$匹配abbd但不匹配ababd,正则表达式^(ab|cd)$匹配ab但不匹配abd。
CMake语言转义序列(Escape Sequences),例如\t、\r、\n和\\可用于构造文字制表符、回车符、换行符和反斜杠(literal tabs, carriage returns, newlines, and backslashes)以传入正则表达式。例如:
带引号的参数"[ \t\r\n]"指定匹配任何单个空白字符的正则表达式;
带引号的参数"[/\\]"指定匹配单个正斜杠/或反斜杠\的正则表达式;
带引号的参数"[A-Za-z0-9_]"指定匹配C语言环境中任何单个"word"字符的正则表达式;
带引号的参数"\\(\\a\\+b\\)"指定匹配确切字符串(a+b)的正则表达式。每个\\在带引号的参数中被解析为只是\,因此正则表达式本身实际上是\(\a\+\b\)。这也可以在括号参数中指定,而不必转义反斜杠,例如[[\(\a\+\b\)]]。
REGEX MATCH:匹配一次<match-regex>并将匹配存储在<out-var>中。所有<input>参数在匹配之前连接(concatenated)。
set(str "123abc123abc")
string(REGEX MATCH "[a-z]" var ${str})
message("var: ${var}") # var: a
string(REGEX MATCH "[1-9]" var ${str})
message("var: ${var}") # var: 1
string(REGEX MATCH "[^1-9]" var ${str})
message("var: ${var}") # var: a
REGEX MATCHALL:尽可能多地匹配<match-regex>并将匹配项作为列表(list)存储在<out-var>中。所有<input>参数在匹配之前连接(concatenated)。
set(str "123abc123abc")
string(REGEX MATCHALL "[a-z]" var ${str})
message("var: ${var}") # var: a;b;c;a;b;c
string(REGEX MATCHALL "[1-9]" var ${str})
message("var: ${var}") # var: 1;2;3;1;2;3
string(REGEX MATCHALL "[^1-9]" var ${str})
message("var: ${var}") # var: a;b;c;a;b;c
REGEX REPLACE:尽可能多地匹配<match-regex>并将<replace-expr>替换为输出中的匹配项。所有<input>参数在匹配之前连接(concatenated)。
set(str "123abc123abc")
set(substr "@#")
string(REGEX REPLACE "[a-z]" ${substr} var ${str})
message("var: ${var}") # var: 123@#@#@#123@#@#@#
string(REGEX REPLACE "[1-9]" ${substr} var ${str})
message("var: ${var}") # var: @#@#@#abc@#@#@#abc
string(REGEX REPLACE "[^1-9]" ${substr} var ${str})
message("var: ${var}") # var: 123@#@#@#123@#@#@#
string(REGEX REPLACE "^a" ${substr} var ${str}) # 若没有找到可replace的,则var=str
message("var: ${var}") # var: 123abc123abc
2.Manipulation:
(1).APPEND:将所有<input>参数追加到<string-var>
set(str1 "csdn addr:")
string(APPEND var ${str1})
set(str2 "https://blog.csdn.net/fengbingchun")
string(APPEND var ${str2})
message("var: ${var}") # var: csdn addr:https://blog.csdn.net/fengbingchun
(2).PREPEND:将所有<input>参数前置(prepend)到<string-var>
set(str1 "https://blog.csdn.net/fengbingchun")
string(PREPEND var ${str1})
set(str2 "csdn addr:")
string(PREPEND var ${str2})
message("var: ${var}") # var: csdn addr:https://blog.csdn.net/fengbingchun
(3).CONCAT:将所有<input>参数连接在一起,并将结果存储在<out-var>中
set(str1 "csdn addr:")
set(str2 "https://blog.csdn.net/fengbingchun")
string(CONCAT var ${str1} ${str2})
message("var: ${var}") # var: csdn addr:https://blog.csdn.net/fengbingchun
(4).JOIN:使用<glue>字符串将所有<input>参数连接在一起,并将结果存储在<out-var>中
set(str1 "csdn addr")
set(str2 "https://blog.csdn.net/fengbingchun")
string(JOIN ": " var ${str1} ${str2})
message("var: ${var}") # var: csdn addr: https://blog.csdn.net/fengbingchun
(5).TOLOWER:将<string>转换为小写字符
set(str "ABC123dEF")
string(TOLOWER ${str} var)
message("var: ${var}") # var: abc123def
(6).TOUPPER:将<string>转换为大写字符
set(str "AbC123dEf")
string(TOUPPER ${str} var)
message("var: ${var}") # var: ABC123DEF
(7).LENGTH:将给定<string>的长度(以字节为单位)存储在<out-var>中。注意:这意味着如果<string>包含多字节字符,则存储在<out-var>中的结果将不是字符数
set(str "https://blog.csdn.net/fengbingchun")
string(LENGTH ${str} var)
message("var: ${var}") # var: 34
(8).SUBSTRING:在<out-var>中存储给定<string>的子字符串。如果<length>为-1,则将返回从<begin>开始的字符串的其余部分。如果<string>比<length>短,则使用字符串的结尾。<begin>和<length>都以字节为单位,因此如果<string>包含多字节字符,则必须小心
set(str "https://blog.csdn.net/fengbingchun")
string(SUBSTRING ${str} 8 13 var)
message("var: ${var}") # var: blog.csdn.net
string(SUBSTRING ${str} 8 100 var)
message("var: ${var}") # var: blog.csdn.net/fengbingchun
string(SUBSTRING ${str} 8 -1 var)
message("var: ${var}") # var: blog.csdn.net/fengbingchun
(9).STRIP:将除去前后空格(leading and trailing spaces removed)的<string>的子字符串存储在<out-var>中
set(str " https://blog.csdn.net/fengbingchun ")
string(STRIP ${str} var)
message("str: ${str}") # str: https://blog.csdn.net/fengbingchun
message("var: ${var}") # var: https://blog.csdn.net/fengbingchun
(10).GENEX_STRIP:从输入<string>中去除"generator expressions"并将结果存储在<out-var>中
set(str "one;$<1:two;three>;four;$<TARGET_OBJECTS:some_target>")
string(GENEX_STRIP "${str}" var) # string(GENEX_STRIP "one;$<1:two;three>;four;$<TARGET_OBJECTS:some_target>" var)
message("var: ${var}") # var: one;four
(11).REPEAT:输出字符串作为输入<string>重复<count>次
set(str "abcd1234")
string(REPEAT ${str} 3 var)
message("var: ${var}") # var: abcd1234abcd1234abcd1234
3.Comparison:比较字符串并将true或false存储在<out-var>中,op有LESS、GREATER、EQUAL、NOTEQUAL、LESS_EQUAL、GREATER_EQUAL
set(str1 "abc")
set(str2 "acd")
string(COMPARE LESS ${str1} ${str2} var)
message("var: ${var}") # var: 1
string(COMPARE GREATER ${str1} ${str2} var)
message("var: ${var}") # var: 0
string(COMPARE EQUAL ${str1} ${str1} var)
message("var: ${var}") # var: 1
string(COMPARE NOTEQUAL ${str1} ${str1} var)
message("var: ${var}") # var: 0
string(COMPARE LESS_EQUAL ${str1} ${str1} var)
message("var: ${var}") # var: 1
string(COMPARE GREATER_EQUAL ${str1} ${str1} var)
message("var: ${var}") # var: 1
4.Hashing:计算<input>字符串的加密哈希(cryptographic hash)。支持的<HASH>算法包括:MD5、SHA1、SHA224、SHA256、SHA384、SHA512、SHA3_224、SHA3_256、SHA3_384、SHA3_512
set(str "https://blog.csdn.net/fengbingchun")
string(MD5 var ${str})
message("var: ${var}") # var: 347626e4d6ac64d0d193e4f7c9a527b1
string(SHA1 var ${str})
message("var: ${var}") # var: d0e47459e1e8115c11f5640e2595c7d35dfa5d4f
string(SHA224 var ${str})
message("var: ${var}") # var: e31ec2e82107a7acee703ea0ef08ea98d68aabad41725e80faf5795e
string(SHA256 var ${str})
message("var: ${var}") # var: 0220d436e044b408464a2d59a06a1af98ced88b17b4dffe7bdfd22420a2703ef
string(SHA384 var ${str})
message("var: ${var}") # var: 510f2226e793a2ef50aff6a7da133489b0f588b67e090f7a131d7f6d098855e22a917867222d0eea53d225689751dda4
string(SHA512 var ${str})
message("var: ${var}") # var: e301205b475e6288b8844d147cf28083f1dc847ea78c332a93061ccc950625acab5e857b76dbf95b5990ee387d935e7b5206f78a05be403bac83b1c0110acbcc
string(SHA3_224 var ${str})
message("var: ${var}") # var: 62f51871f691fb594f70f5e353f98e310f98c0e7f1030ed49e01747e
string(SHA3_256 var ${str})
message("var: ${var}") # var: 442a3127fd33cf6b89427b819dfb69c64f7805214fd1ff4c77bd33e85deebd99
string(SHA3_384 var ${str})
message("var: ${var}") # var: af8c8e24e984eee9874336401d3140b971074dcf94be3b7955350a8845143c09d318773e6d34da7347295af52308eec6
string(SHA3_512 var ${str})
message("var: ${var}") # var: ef3c281c1745c06c113f3e8d92acdc006a1f665f7fbc48b58f6fb871cb31bdb3f28e81c7f6e268b75d5861cf160720072f475f94f75335d7492ca14e1f0963a7
5.Generation:
(1).ASCII:将所有数字转换为对应的ASCII字符
set(num 33)
string(ASCII ${num} var)
message("var: ${var}") # var: !
string(ASCII 33 34 var)
message("var: ${var}") # var: !"
string(ASCII 256 var) # CMake Error at test_string.cmake:159 (string):
# string Character with code 256 does not exist.
(2).HEX:将输入的<string>中的每个字节转换为十六进制表示,并将连接后的十六进制数字存储在<out-var>中。输出中的字母(a到f)是小写的
set(str "!#$<=>Zz")
string(HEX ${str} var)
message("var: ${var}") # var: 2123243c3d3e5a7a
(3).CONFIGURE:像configure_file命令一样的规则转换<string>
set(csdn_addr "https://blog.csdn.net/fengbingchun")
string(CONFIGURE "#cmakedefine csdn_addr @csdn_addr@" var)
message("var: ${var}") # var: #define csdn_addr https://blog.csdn.net/fengbingchun
(4).MAKE_C_IDENTIFIER:将<string>中的每个非字母数字字符(each non-alphanumeric character)转换为下划线并将结果存储在<out-var>中。如果<string>的第一个字符是数字,则下划线也将被添加到结果前
set(str "123^$abc*()ABC")
string(MAKE_C_IDENTIFIER ${str} var)
message("var: ${var}") # var: _123__abc___ABC
(5).RANDOM:返回由<alphabet>中的字符组成的长度为<length>的随机字符串。默认长度为5个字符,默认字母为所有数字和大小写字母。如果给定一个整数<seed>,它的值将用于为随机数生成器提供种子(seed)
string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>] [RANDOM_SEED <seed>] <output_variable>)
string(RANDOM LENGTH 20 ALPHABET abc123ABC RANDOM_SEED 5 var)
message("var: ${var}") # var: caCabac22CacCb1c1c1c
(6).TIMESTAMP:将当前日期/或时间的字符串表示形式写入<out-var>。如果命令无法获取时间戳,<out-var>将设置为空字符串。
可选的UTC标志请求当前日期/时间表示为协调世界时(UTC)而不是本地时间。
可选的<format string>可能包含以下格式说明符:%%、%d、%H、%I、%j、%m、%b、%B、%M、%s、%S、%f、%U、%w、%a、%A、%y、%Y
string(TIMESTAMP var) # %Y-%m-%dT%H:%M:%S for local time
message("var: ${var}") # var: 2022-11-05T09:23:29
string(TIMESTAMP var UTC) # %Y-%m-%dT%H:%M:%SZ for UTC
message("var: ${var}") # var: 2022-11-05T01:23:29Z
string(TIMESTAMP var %B:%U)
message("var: ${var}") # var: November:44
(7).UUID:基于<namespace>(其本身必须是有效的UUID)和<name>的组合值的哈希创建一个通用唯一标识符(GUID)。哈希算法可以是MD5或SHA1。UUID的格式为:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,其中每个x代表一个小写十六进制字符。如果需要,可以使用可选的UPPER标志请求大写表示。
string(UUID <output_variable> NAMESPACE <namespace> NAME <name> TYPE <MD5|SHA1> [UPPER])
string(UUID var NAMESPACE 34795e00-5a50-11ed-9b6a-0242ac120002 NAME beijing TYPE SHA1 UPPER)
message("var: ${var}") # var: B4383795-34FD-5079-BFC8-38E44E159A5D
string(UUID var NAMESPACE 34795e00-5a50-11ed-9b6a-0242ac120002 NAME beijing TYPE MD5)
message("var: ${var}") # var: fe7b8cbc-9a61-333e-aaad-b7acb502e9ac
6.JSON:查询JSON字符串。如果给出了可选的ERROR_VARIABLE参数,则会在<error-var>中报告错误;并且<out-var>将设置为<member|index>-[<member|index>...]-NOTFOUND,或者如果没有相关path,则仅设置为NOTFOUND。如果发生error但ERROR_VARIABLE选项不存在,则会触发fatal error。如果没有发生error,<error-var>将设置为NOTFOUND。
GET:通过给定的<member|index>从<json-string>获取元素。array和object元素将作为JSON字符串返回。boolean元素将作为ON或OFF返回。null元素将作为空字符串返回。number和string类型将作为字符串返回。
TYPE:通过给定的<member|index>从<json-string>获取元素的类型。<out-var>将设置为NULL, NUMBER, STRING, BOOLEAN, ARRAY或OBJECT。
LENGTH:通过给定的<member|index>从<json-string>获取元素的长度。需要元素为array或object类型。
REMOVE:通过给定的<member|index>从<json-string>中删除一个元素。没有移除元素的JSON字符串将存储在<out-var>中。
MEMBER:通过给定的<member|index>从<json-string>中获取第<index>成员的名称。需要元素为object类型。
SET:设置<json-string>中的元素,将<member|index>设置为<value>。<value>应该是有效的JSON。
EQUAL:比较<json-string1>和<json-string2>给出的两个JSON objects是否相等。<json-string1>和<json-string2>的内容应该是有效的JSON。如果认为JSON objects相等,则<out-var>将设置为true,否则设置为false。
set(str
"{
\"name1\": \"csdn\",
\"url1\": \"https://blog.csdn.net/fengbingchun\",
\"name2\": \"github\",
\"url2\": \"https://github.com/fengbingchun\"
}"
)
string(JSON var ERROR_VARIABLE error_var GET ${str} "url1") # GET
message("var: ${var}") # var: https://blog.csdn.net/fengbingchun
string(JSON var ERROR_VARIABLE error_var TYPE ${str} "name1") # TYPE
message("var: ${var}") # var: STRING
string(JSON var ERROR_VARIABLE error_var LENGTH ${str} "name1") # LENGTH
message("var: ${var}, err: ${error_var}") # var: name1-NOTFOUND, err: LENGTH needs to be called with an element of type ARRAY or OBJECT, got STRING
string(JSON var ERROR_VARIABLE error_var REMOVE ${str} "name1") # REMOVE
message("var: ${var}") # var: {
# "name2" : "github",
# "url1" : "https://blog.csdn.net/fengbingchun",
# "url2" : "https://github.com/fengbingchun"
# }
string(JSON var ERROR_VARIABLE error_var MEMBER ${str} "name1") # MEMBER
message("var: ${var}, err: ${error_var}") # var: name1-NOTFOUND, err: expected an array index, got: 'name1'
string(JSON var ERROR_VARIABLE error_var SET ${str} "name1" ${str}) # SET
message("var: ${var}") # var: {
# "name1" :
# {
# "name1" : "csdn",
# "name2" : "github",
# "url1" : "https://blog.csdn.net/fengbingchun",
# "url2" : "https://github.com/fengbingchun"
# },
# "name2" : "github",
# "url1" : "https://blog.csdn.net/fengbingchun",
# "url2" : "https://github.com/fengbingchun"
# }
string(JSON var ERROR_VARIABLE error_var EQUAL ${str} ${str}) # EQUAL
message("var: ${var}") # var: ON
string(JSON var ERROR_VARIABLE error_var EQUAL ${str} "{}") # EQUAL
message("var: ${var}") # var: OFF
执行上述测试代码需要3个文件:build.sh, CMakeLists.txt, test_string.cmake
build.sh内容如下:
#! /bin/bash
# supported input parameters(cmake commands)
params=(function macro cmake_parse_arguments \
find_library find_path find_file find_program find_package \
cmake_policy cmake_minimum_required project include \
string list set)
usage()
{
echo "Error: $0 needs to have an input parameter"
echo "supported input parameters:"
for param in ${params[@]}; do
echo " $0 ${param}"
done
exit -1
}
if [ $# != 1 ]; then
usage
fi
flag=0
for param in ${params[@]}; do
if [ $1 == ${param} ]; then
flag=1
break
fi
done
if [ ${flag} == 0 ]; then
echo "Error: parameter \"$1\" is not supported"
usage
exit -1
fi
if [[ ! -d "build" ]]; then
mkdir build
cd build
else
cd build
fi
echo "==== test $1 ===="
cmake -DTEST_CMAKE_FEATURE=$1 ..
CMakeLists.txt内容如下:
cmake_minimum_required(VERSION 3.22)
project(cmake_feature_usage)
message("#### current cmake version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}")
include(test_${TEST_CMAKE_FEATURE}.cmake)
message("==== test finish ====")
test_string.cmake:为上面所有示例代码
可能的执行结果如下图所示:
GitHub: https://github.com/fengbingchun/Linux_Code_Test