​https://cmake.org/cmake/help/latest/command/string.html​

任何一种语言,操作字符串是最基础的,特别是cmake它的所只支持一种数据类型 --- 字符串。

Search and Replace

纯字符串查找和替换

查找

string(FIND <string> <substring> <output_variable> [REVERSE])
  • 从给字的string中查找子串substring返回子串在string中的位置
  • 如果提供了REVERSE标记,则从string的末尾开始查找
  • 如果没有找到则返回 -1

从上面的的描述中,不难得返回的是第一次匹配的位置:

string(FIND /abb/cc/dd/efg/cc/ddb cc res)
message(${res}) # 5

string(FIND /abb/cc/dd/efg/cc/ddb cc res REVERSE)
message(${res}) # 15

set(MY_STR /abb/cc/dd/efg/cc/ddb)
string(FIND MY_STR cc res REVERSE)
message(${res}) # -1

set(MY_STR /abb/cc/dd/efg/cc/ddb)
string(FIND ${MY_STR} cc res REVERSE)
message(${res}) # 15

替换

string(REPLACE <match_string>
<replace_string> <output_variable>
<input> [<input>...])

先看最基本的用法--只有一个input

set(MY_STR /abb/cc/dd/efg/cc/ddb)
string(REPLACE cc xx RESULT ${MY_STR})

message(${RESULT}) # /abb/xx/dd/efg/xx/ddb

从输出结果可看出,是全局替换!!

多个input是什么情况??

set(MY_STR /abb/cc/dd/efg/cc/ddb)
string(REPLACE cc xx RESULT ${MY_STR} --other/cc/bb/ff/dd)

message(${RESULT}) # /abb/xx/dd/efg/xx/ddb--other/xx/bb/ff/dd

如果有多个input,output是所有input替换后再拼接起来...

如果RESULT有初始值,替换结果只是追加到初始值之后,并不会覆盖原来的值!

使用正则查找和替换

先看看如何指定正则

^

配置输入的开始

$

配置输入的结束

.

任何单个字符

\<char>

如\a 匹配字符'a'

[]

匹配括号内的字符

[^]

not[]

-

[a-z]表示[a到z],[+*/-]放在最后就是代表'-'

*

匹配前面的模式 0 或 多次

匹配前面的模式 0 或 1次

+

匹配前面的模式 1 或 多次

|

pattern1|pattern2匹配pattern1或pattern2

()

分组,在正则替换中,可以引用被匹配的分组

注意:没有 {n}或{n,m}的操作符!!

关于优先级

*+和?(和次数相关的)的优先级高于串连操作(比如abce表a串连b串连c...), | 低于串连操作,这就意味着:
1) ab+cb匹配abbcb但不匹配ababcb(先运算ab,然后才是+)
2) ab|cd匹配ab 或 cd 但不匹配 abc或abd

关于转义

  • [\t\r\n] 匹配空白符
  • [/\\] 匹配 ‘/\’
  • \\(\\a\\+b\\) --> \\ - \ 所以它表示的是 \(\a\+b\),
    可以使用括号参数 [[ \(\a\+b\)]]

查找

string(REGEX MATCH|MATCHALL <regular_expression>
<output_variable> <input> [<input>...])

从input中把与regular_expression匹配的结果追加到output_variable

string(REGEX MATCH [[.*\.txt]] RESULT a.txt -b.txt c.avi d.jpg)
message(${RESULT}) # a.txt-b.txt

为了输出好看一点,我故意在b.txt之前加了-

MATCHALL:

string(REGEX MATCHALL [[\.txt]] RESULT "a.txt split -b.txt")
message(${RESULT}) #.txt.txt
string(REGEX MATCH [[\.txt]] RESULT "a.txt split -b.txt")
message(${RESULT}) #.txt

替换

string(REGEX REPLACE <regular_expression>
<replacement_expression> <output_variable>
<input> [<input>...])

可以通过 \1, \2 ... \9 引用之前匹配到的分组,在cmake通过\\来获得一个\如:\\1

string(REGEX REPLACE [[(.*)(\.txt|\.png)]] \\1.jpg RESULT a.txt -b.png -c.jpg)
message(${RESULT})# a.txt-b.jpg-c.jpg

在内部好像是先把所有的input合并再执行替换操作,也没有非贪婪模式...

Manipulation

string(APPEND <string_variable> [<input>...])
string(PREPEND <string_variable> [<input>...])

string(APPEND RESULT a)
string(PREPEND RESULT pre-)
string(APPEND RESULT .txt)
message(${RESULT}) # pre-a.txt

string_variable在原来的基础上,前插或向后追加...

string(CONCAT <output_variable> [<input>...])

string(APPEND RESULT a)
string(PREPEND RESULT pre-)
string(APPEND RESULT .txt)

string(CONCAT RESULT text .txt)
message(${RESULT}) # text.txt

RESULT被覆盖了...

string(JOIN <glue> <output_variable> [<input>...])

string(APPEND RESULT a)
string(PREPEND RESULT pre-)
string(APPEND RESULT .txt)

string(CONCAT RESULT text .txt)

string(JOIN - RESULT BB CC DD)
message(${RESULT}) # BB-CC-DD

glue有类似于分隔符的作用...

string(TOLOWER <string> <output_variable>)
string(TOUPPER <string> <output_variable>)
string(LENGTH <string> <output_variable>)
string(SUBSTRING <string> <begin> <length> <output_variable>)
string(STRIP <string> <output_variable>)# 去除两端空白
string(REPEAT <string> <count> <output_variable>) # string 重复 count次

Comparison

string(COMPARE LESS <string1> <string2> <output_variable>)
string(COMPARE GREATER <string1> <string2> <output_variable>)
string(COMPARE EQUAL <string1> <string2> <output_variable>)
string(COMPARE NOTEQUAL <string1> <string2> <output_variable>)
string(COMPARE LESS_EQUAL <string1> <string2> <output_variable>)
string(COMPARE GREATER_EQUAL <string1> <string2> <output_variable>)

比较,将结果(true/false)保存到output_variable中

Hashing

string(<HASH> <output_variable> <input>)

根据字符串计算hash值,不知道是干什么用的,我是没用过的...

​https://cmake.org/cmake/help/latest/command/string.html#hashing​

Generation

string(ASCII <number> [<number> ...] <output_variable>)

string(ASCII 65 66 RESULT)
message(${RESULT}) # 6566 --> 把数字转成对应的ASCII码
string(HEX <string> <output_variable>) # 要求在3.18以上

我现在用的是3.16,所以这个函数并没有试过.

string(CONFIGURE <string> <output_variable>
[@ONLY] [ESCAPE_QUOTES])

和​ ​​​configure_file()​​一样,没用过,略过吧...

随机字符串

string(MAKE_C_IDENTIFIER <string> <output_variable>)

string(MAKE_C_IDENTIFIER ABCD+C67&F RESULT)
message(${RESULT}) # ABCD_C67_F, 非数字或字母的都转成_
string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>]
[RANDOM_SEED <seed>] <output_variable>)

string(RANDOM LENGTH 10 RESULT)
message(${RESULT}) # ou5wr ->产生随机的字符串

LENGTH 默认是 5

生成时间戳

string(TIMESTAMP <output_variable> [<format_string>] [UTC])

​%%​

New in version 3.8.

A literal percent sign (%).

​%d​

The day of the current month (01-31).

​%H​

The hour on a 24-hour clock (00-23).

​%I​

The hour on a 12-hour clock (01-12).

​%j​

The day of the current year (001-366).

​%m​

The month of the current year (01-12).

​%b​

New in version 3.7.

Abbreviated month name (e.g. Oct).

​%B​

New in version 3.10.

Full month name (e.g. October).

​%M​

The minute of the current hour (00-59).

​%s​

New in version 3.6.

Seconds since midnight (UTC) 1-Jan-1970 (UNIX time).

​%S​

The second of the current minute. 60 represents a leap second. (00-60)

​%f​

The microsecond of the current second (000000-999999).

​%U​

The week number of the current year (00-53).

​%V​

New in version 3.22.

The ISO 8601 week number of the current year (01-53).

​%w​

The day of the current week. 0 is Sunday. (0-6)

​%a​

New in version 3.7.

Abbreviated weekday name (e.g. Fri).

​%A​

New in version 3.10.

Full weekday name (e.g. Friday).

​%y​

The last two digits of the current year (00-99).

​%Y​

The current year.

string(TIMESTAMP RESULT %Y-%m-%d)
message(${RESULT})

JSON

查询字json字符串,不知道在什么地方有用,或许是可以从配置文件中读取到json格式的配置再查询吧...

​https://cmake.org/cmake/help/latest/command/string.html#json​