CMake指令:string(字符串操作)

发布于:2025-06-03 ⋅ 阅读:(20) ⋅ 点赞:(0)

目录

1.简介

2.常用命令介绍

2.1.字符串查找(Find)

2.2.正则匹配(REGEX MATCH)

2.3.字符串替换(REPLACE)

2.4.正则匹配替换(REGEX REPLACE)

2.5.截取子串(SUBSTRING)

2.6.大小写转换(TOUPPER/TOLOWER)

2.7.去除字符串首尾的空格或指定字符(STRIP)

2.8.字符串分割(SPLIT)

2.9.字符串连接(JOIN)

2.10.字符串长度(LENGTH)

2.11.字符串比较(COMPARE)

2.13.字符串串联(CONCAT)

2.14.字符串附加(APPEND)

2.15.根据模板生成字符串(GENERATE)

2.16.计算字符串的哈希值(HASH)

3.字符串连接CONCAT和字符串附加APPEND的区别

4.典型应用场景

5.注意事项


1.简介

  string 命令是 CMake 中处理文本的核心工具,支持字符串的查找、替换、转换、分割、生成等操作。其功能类似编程语言中的字符串库,可用于构建路径处理、版本号解析、代码生成等场景。string 指令的基本语法如下:

string(<command> ...)

<command> : 是您希望执行的操作类型,比如 LENGTH,APPEND,REPLACE 等。
     LENGTH:计算字符串的长度。
     APPEND:将一个字符串附加到另一个字符串后面。
     REPLACE:替换字符串中的一部分内容。
     SUBSTRING:提取字符串的子字符串。
     COMPARE:比较两个字符串大小,是否相等。
     TOUPPER/TOLOWER:将字符串转换为大写/小写。
     REGEX REPLACE:字符串查找和替换,使用正则表达式匹配和替换字符串的某些部分。
     CONCAT:字符串连接。
     FIND:用于在字符串中查找一个子字符串位置。
     REGEX MATCH:用于在字符串中查找正则表达式匹配的内容。
               。。。
…: 后面的形参根据不同的指令各有差异,下面我们会根据command类型一一示例进行介绍。

2.常用命令介绍

2.1.字符串查找(Find)

查找子串在字符串中的位置(索引从 0 开始,未找到返回 -1):

string(FIND <string> <substring> <output_variable> [REVERSE])

        在 <string> 中查找 <substring> 的位置,位置基础是从0开始,结果是<substring> 开始的索引,存储在 <output_variable> 中,如果没找到,输出 -1。可选的[REVERSE]参数表示从字符串的末尾开始向前搜索。使用REVERSE选项对于查找最后一次出现的位置特别有用,尤其是在处理包含多个相同子字符串的长字符串时。这提供了一种灵活的方式来从不同的方向分析和处理字符串数据。

        示例如下:

string(FIND "hello world" "world" pos)  # pos = 6  
string(FIND "hello world" "x" pos)      # pos = -1  

2.2.正则匹配(REGEX MATCH)

string(REGEX MATCH <regex> <output variable> <input> [<input>...])

        这个模式用于在输入字符串中查找与正则表达式匹配的部分。如果找到匹配的部分,它将被存储在输出变量中。

示例如下:

#匹配数字
string(REGEX MATCH "[0-9]+" "version 1.2.3" version_num)  # version_num = 1

# 设置包含数字的文本字符串
set(input_text "The 2 quick brown foxes jump over 13 lazy dogs 8 times.")

# 使用正则表达式匹配所有数字
string(REGEX MATCHALL "[0-9]+" matched_numbers ${input_text})

# 打印匹配到的所有数字
message("Matched numbers are: ${matched_numbers}")
  

2.3.字符串替换(REPLACE)

替换字符串中的子串(非正则匹配):

string(REPLACE <match> <replace> <output_variable> <string>)

<string>字符串中搜索 <match> 并将其替换为<replace>,结果存储在 <output_variable> 中。

示例如下:

string(REPLACE "world" "CMake" "hello world" result)  # result = "hello CMake"  

2.4.正则匹配替换(REGEX REPLACE)

使用正则表达式替换匹配的部分:

string(REGEX REPLACE <regex> <replace> <output_variable> <string>)

对 <string> 使用正则表达式 <regex> 进行查找,并用<replace> 进行替换,结果存储在 <output_variable> 中。

示例如下:

string(REGEX REPLACE "([0-9]+)\\.([0-9]+)" "v\\1_\\2" "1.2" version)  # version = "v1_2"  

2.5.截取子串(SUBSTRING)

截取字符串的子串:

string(SUBSTRING <string> <begin> <length> <output_variable>)

提取 <string> 的子字符串,从 <begin> 开始,长度为 <length>,结果存储在 <output_variable> 中。

示例如下:

#1
string(SUBSTRING "hello" 1 3 result)  # result = "ell" (索引 1 开始,长度 3)  

#2
set(MY_STR "Hello, world!")
string(SUBSTRING "${MY_STR}" 0 5 SUB_STR)
message(STATUS "子字符串: ${SUB_STR}")  # 输出应为 "Hello"

2.6.大小写转换(TOUPPER/TOLOWER)

转换字符串大小写:

string(TOUPPER <string> <output_variable>)  
string(TOLOWER <string> <output_variable>)  

示例如下:

string(TOUPPER "hello" upper)  # upper = "HELLO"  

2.7.去除字符串首尾的空格或指定字符(STRIP)

去除字符串首尾的空格或指定字符:

string(STRIP <string> <output_variable>)  

示例如下:

string(STRIP "  hello  " result)  # result = "hello"  

2.8.字符串分割(SPLIT)

按分隔符将字符串拆分为列表(类似 Python 的 split()):

string(SPLIT <string> <delimiter> <output_variable>)  

示例如下:

string(SPLIT "a;b;c" ";" list_var)  # list_var = ["a", "b", "c"]  

2.9.字符串连接(JOIN)

用分隔符连接列表为字符串(类似 Python 的 join()):

string(JOIN <delimiter> <output_variable> <input1> <input2> ...)  

示例如下:

string(JOIN "," output "a" "b" "c")  # output = "a,b,c"  

2.10.字符串长度(LENGTH)

获取字符串长度:

string(LENGTH <string> <output_variable>)  

示例如下:

string(LENGTH "hello" len)  # len = 5  

2.11.字符串比较(COMPARE)

字符串比较有两种方法。
1.通过条件语句使用 STREQUALSTRLESS 和 STRGREATER 来比较字符串

STREQUAL:字符串相等比较。如果相等,则表达式结果为 TRUE,否则为 FALSE。
STRLESS:用于判断一个字符串是否在字典排序上小于另一个字符串。如果是,则表达式结果为 TRUE,否则为 FALSE。
STRGREATER:用于判断一个字符串是否在字典排序上大于另一个字符串。如果是,则表达式结果为 TRUE,否则为 FALSE。

示例如下:

set(var1 "Hello")
set(var2 "World")

if("${var1}" STRLESS "${var2}")
  message(STATUS "var1 is less than var2.")
else()
  message(STATUS "var1 is not less than var2.")
endif()

if("${var1}" STRGREATER "${var2}")
  message(STATUS "var1 is greater than var2.")
else()
  message(STATUS "var1 is not greater than var2")
endif()

if("${var1}" STREQUAL "${var2}")
  message(STATUS "var1 is equal to var2.")
else()
  message(STATUS "var1 is not equal to var2.")
endif()

2.另一种比较字符串的方法

string(COMPARE <op> <string1> <string2> <output variable>)

这里的<op>是比较操作符,<op>EQUALLESSGREATER,比较结果的返回值同上面STREQUALSTRLESSSTRGREATER<string1><string2>是要比较的字符串,而<output variable>是用来存储比较结果的变量。

set(var1 "Hello")
set(var2 "World")

string(COMPARE EQUAL "${var1}" "${var2}" result)
if(result)
    message(STATUS "The strings are equal")
else()
    message(STATUS "The strings are not equal")
endif()

string(COMPARE LESS "${var1}" "${var2}" result)
if(result)
    message(STATUS "var1 is less than var2")
else()
    message(STATUS "var1 is not less than var2")
endif()

string(COMPARE GREATER "${var1}" "${var2}" result)
if(result)
    message(STATUS "var1 is greater than var2")
else()
    message(STATUS "var1 is not greater than var2")

2.13.字符串串联(CONCAT)

string(CONCAT <output_variable> <input> …)

将所有 <input> 字符串拼接起来,结果存储在 <output_variable> 中

示例如下:

set(STR1 "Hello, ")
set(STR2 "World!")
string(CONCAT CONNECTED_STR ${STR1} ${STR2})
message(STATUS "Connected string: ${CONNECTED_STR}")

2.14.字符串附加(APPEND)

string(APPEND <variable> <string> [<string>...])

将一个或多个 <string> 附加到变量 <variable> 的值上。

示例如下:

# 初始为空的编译标志
set(COMPILER_FLAGS "")

# 根据需要附加标志
string(APPEND COMPILER_FLAGS "-Wall ")
string(APPEND COMPILER_FLAGS "-Werror ")
string(APPEND COMPILER_FLAGS "-O3")

# 打印最终的编译标志
message(STATUS "Compiler flags: ${COMPILER_FLAGS}")

注意事项:

1.在指定多个值进行追加时,string(APPEND …)不会在这些值之间自动添加任何分隔符。如果需要分隔符(如空格或其他字符),你必须自己包括它们在值中。
2.和大部分CMake命令一样,string(APPEND …)修改变量的作用是在原地执行的,意味着它直接改变了传入的变量而不是返回一个新的修改后的副本。

2.15.根据模板生成字符串(GENERATE)

根据模板生成字符串(常用于生成配置文件):

string(GENERATE <output_file> <content> [ESCAPE_QUOTES])  

示例如下:

string(GENERATE "config.h" "#define VERSION \"${PROJECT_VERSION}\"")  

2.16.计算字符串的哈希值(HASH)

计算字符串的哈希值(支持 MD5/SHA1/SHA256 等):

string(HASH <algorithm> <output_variable> <string>)  

示例如下:

string(HASH SHA256 hash "hello")  # hash = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9"  

3.字符串连接CONCAT和字符串附加APPEND的区别

1.string(CONCAT ...):创建新字符串

将多个字符串参数连接成一个新字符串,并存储到指定变量中。原字符串不会被修改。

string(CONCAT full_name "John" " " "Doe")  # full_name = "John Doe"

# 结合变量使用
set(PREFIX "lib")
set(NAME "mylib")
set(EXT ".a")
string(CONCAT LIB_FILE ${PREFIX} ${NAME} ${EXT})  # LIB_FILE = "libmylib.a"

2.string(APPEND ...):追加到已有字符串

将一个或多个字符串追加到已有变量的末尾,直接修改原变量的值。若变量不存在,则创建并初始化。

set(message "Hello")
string(APPEND message " World!")  # message 变为 "Hello World!"

# 多次追加
string(APPEND message " Have a nice day.")  # message 变为 "Hello World! Have a nice day."

3.核心区别对比

特性 string(CONCAT ...) string(APPEND ...)
是否创建新变量 必须指定新变量存储结果 直接修改已有变量(若不存在则创建)
原字符串是否修改
典型场景 一次性拼接多个字符串 逐步构建字符串(如循环追加)
示例 string(CONCAT out "a" "b" "c") string(APPEND var "a";"b";"c")

4.使用场景对比

CONCAT 适用场景:

  • 构建路径或文件名(如 bin/${PROJECT_NAME})。
  • 生成版本号字符串(如 v${VERSION_MAJOR}.${VERSION_MINOR})。
  • 一次性拼接多个固定字符串。

APPEND 适用场景:

  • 逐步构建编译选项(如 string(APPEND CMAKE_CXX_FLAGS " -Wall -Werror"))。
  • 循环追加内容(如收集所有源文件路径):
set(SOURCES "")
foreach(file IN LISTS file_list)
    string(APPEND SOURCES "${file};")  # 追加并以分号分隔
endforeach()
  • 动态生成配置文件内容:
string(APPEND config_content "#define VERSION ${PROJECT_VERSION}\n")
string(APPEND config_content "#define DEBUG ${DEBUG_MODE}\n")

4.典型应用场景

1.版本号解析

set(VERSION "1.2.3")  
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" _ ${VERSION})  
set(VERSION_MAJOR ${CMAKE_MATCH_1})  # 1  
set(VERSION_MINOR ${CMAKE_MATCH_2})  # 2  
set(VERSION_PATCH ${CMAKE_MATCH_3})  # 3  

2.路径处理

set(PATH "/usr/local/bin")  
string(REPLACE "/" ";" PATH_LIST ${PATH})  # PATH_LIST = ["usr", "local", "bin"]  

3.条件编译配置

if(DEBUG)  
    string(APPEND CMAKE_CXX_FLAGS " -DDEBUG=1")  
endif()  

5.注意事项

1.正则表达式语法

  • CMake 的正则语法类似 Perl,但需注意转义(如 \\ 表示反斜杠)。
  • 常用元字符:^(开头)、$(结尾)、[0-9](数字)、.*(任意字符)。

2.字符串与列表转换

  • CMake 列表本质是分号分隔的字符串,可通过 string(SPLIT) 和 string(JOIN) 相互转换。

3.变量作用域

  • 字符串操作结果需存入变量,不会直接修改原字符串(除非覆盖同名变量)。

通过灵活使用 string 命令,可高效处理 CMake 中的文本逻辑,避免复杂的外部脚本依赖。

相关链接


网站公告

今日签到

点亮在社区的每一天
去签到