- 编程语言
- 编译器
- 云原生
- 语言运行时
【免费下载链接】wing
A programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡
导读
本文以 docs/api/04-standard-library/std/string.md 中定义的String类 API 为骨架,系统讲解 Wing 语言内置字符串类型str的全部方法:字符访问、子串查询、大小写转换、查找替换、拆分合并、去除空白,以及将Json安全转换为str的静态方法fromJson。读完本文,你将掌握str类型每一个方法的签名、参数语义、边界行为与典型用法,并能借助仓库中的源码实现与测试用例理解其底层机制,在编写云端应用(如日志解析、请求参数校验、数据格式化)时熟练运用。
str是 Wing 语言的原生(primitive)类型之一,在 docs/api/05-language-reference.md 中被描述为UTF-16 编码的字符串,其完整 API 由 SDK 中的String类暴露给编译器,语言层面通过@wingType str注解将其绑定为str关键字(见 packages/@winglang/sdk/src/std/string.ts)。
一、字符串字面量与基础性质
1.1 字符串字面量:插值、多行与转义
在 Wing 中,字符串用双引号声明,并且所有声明形式都支持多行。普通字符串内部会处理形如{<expression>}的表达式替换(插值),行为类似于 JavaScript 的`text ${sub.prop}`模板字符串,同时支持 Unicode 转义序列;在插值表达式内部,"与{可以通过反斜杠\转义。参见 docs/api/05-language-reference.md:
let name = "World"; let s = "Hello, {name}!"; let l = s.length; // 11字符串连接也可以直接使用+运算符与+=赋值运算符。来自 tests/valid/std_string.test.w 的验证:
assert("hello" + " world" == "hello world"); let var initial = "hey, "; initial += "you"; assert(initial == "hey, you");多行字符串中的换行与显式\n转义是等价的:
let s3 = "hello world"; let s4 = "hello\nworld"; assert(s3 == s4);1.2length属性
String类暴露的唯一属性,类型为num,表示字符串的长度(UTF-16 编码下的字符数量)。
length: num;assert("hello".length == 5); assert("".length == 0);示例与边界行为均可在 tests/sdk_tests/std/string.test.w 中验证:空字符串长度为0。
二、查询类方法:contains、startsWith、endsWith、indexOf
这组方法用于判断字符串是否包含某个子串,或在何处出现,返回值均为bool/num。
2.1contains(searchString: str): bool
检查字符串是否包含指定子串(区分大小写)。
contains(searchString: str): boolassert("hello wing".contains("hello")); assert(!"hello wing".contains("Hello")); // 大小写敏感 assert("hello wing".contains("w"));2.2startsWith(searchString: str): bool与endsWith(searchString: str): bool
分别判断字符串是否以给定子串开头 / 结尾。
startsWith(searchString: str): bool endsWith(searchString: str): boolassert("hello wing".startsWith("h")); assert(!"hello wing".startsWith("H")); // 大小写敏感 assert(!"hello wing".startsWith("w")); assert("boom".endsWith("m")); assert(!"boom".endsWith("b"));2.3indexOf(searchString: str): num
返回searchString在字符串中第一次出现的索引(从 0 开始);若未找到,返回-1。
indexOf(searchString: str): numassert("boom".indexOf("m") == 3); assert("boom".indexOf("a") == -1); // 未找到返回 -1上述四类查询的测试用例见 tests/sdk_tests/std/string.test.w 与 tests/sdk_tests/std/string.test.w。
三、提取与切片:at、substring
3.1at(index: num): str
返回指定索引处的单个字符。关键特性:支持负索引,负数从字符串末尾倒数计数。越界(索引超出[0, length)或负索引超出范围)会抛出运行时错误"index out of bounds"。
at(index: num): strassert("boom".at(0) == "b"); assert("boom".at(2) == "o"); // 负索引:从末尾倒数 assert("boom".at(-1) == "m"); assert("boom".at(-4) == "b"); // 越界抛出异常 // "boom".at(4) -> Error: index out of bounds // "boom".at(-5) -> Error: index out of bounds在源码 packages/@winglang/sdk/src/std/string.ts 中,at通过一条@macro编译期展开实现越界检查:
if ($args$ >= $self$.length || $args$ + $self$.length < 0) { throw new Error("index out of bounds") }也就是说,越界保护在编译期由宏生成,运行时由 JS 层执行。完整测试见 tests/sdk_tests/std/string.test.w。
3.2substring(indexStart: num, indexEnd?: num): str
截取从indexStart开始、到indexEnd结束(不含indexEnd)的子串。indexEnd为可选参数,省略时截取到字符串末尾。
substring(indexStart: num, indexEnd?: num): strassert("hello wing".substring(0, 5) == "hello"); assert("hello wing".substring(5) == "wing"); assert("hello wing".substring(5, 7) == "wi"); // 超出末尾的结束索引会被安全截断到字符串长度 assert("hello wing".substring(0, 100) == "hello wing");测试见 tests/sdk_tests/std/string.test.w 与 tests/valid/std_string.test.w。
四、修改与变换:replace、replaceAll、lowercase、uppercase、trim、concat、split
这组方法产生新的字符串(或数组),原始字符串不变——str是不可变类型。
4.1replace(searchString: str, replaceString: str): str与replaceAll(searchString: str, replaceString: str): str
replace:只替换第一次出现的子串。replaceAll:替换所有出现的子串。
replace(searchString: str, replaceString: str): str replaceAll(searchString: str, replaceString: str): strassert("foo".replace("o", "0") == "f0o"); // 只替换第一处 assert("foo".replaceAll("o", "0") == "f00"); // 替换全部 assert("hello world".replace("world", "wing") == "hello wing"); assert("hello world world".replaceAll("world", "wing") == "hello wing wing"); assert("hello world".replace("wing", "☁") == "hello world"); // 未命中则原样返回 assert("hello world world".replaceAll(" ", "-") == "hello-world-world"); assert("".replace("", "hello world") == "hello world"); // 空字符串也能匹配replace在源码中通过@macro $self$.replace(...$args$)展开为 JS 原生方法,replaceAll展开为$self$.replaceAll(...$args$)(见 packages/@winglang/sdk/src/std/string.ts)。完整测试见 tests/sdk_tests/std/string.test.w。
4.2lowercase(): str与uppercase(): str
分别返回全小写 / 全大写的新字符串。对非字母字符(数字、符号)无影响。
lowercase(): str uppercase(): strassert("BOOM".lowercase() == "boom"); assert("BooM".lowercase() == "boom"); assert("123#@".lowercase() == "123#@"); assert("BooM".uppercase() == "BOOM"); assert("boom".uppercase() == "BOOM"); assert("123#@".uppercase() == "123#@");源码中二者分别通过宏展开为 JS 的toLocaleLowerCase()与toLocaleUpperCase()(见 packages/@winglang/sdk/src/std/string.ts 与 packages/@winglang/sdk/src/std/string.ts),即遵循本地化规则进行大小写转换。测试见 tests/sdk_tests/std/string.test.w。
4.3trim(): str
移除字符串首尾的空白字符(空格、制表符\t、换行\n等),不处理字符串内部的空白。
trim(): strassert("hello wing ".trim() == "hello wing"); assert("\thello wing\n".trim() == "hello wing"); assert("".trim() == ""); assert(" some string ".trim() == "some string");测试见 tests/sdk_tests/std/string.test.w。
4.4concat(strN: str): str
将一个(或多个)字符串拼接在当前字符串之后,返回新的字符串。
concat(strN: str): strassert("boom".concat("boom") == "boomboom"); assert("some string".concat("s are immutable") == "some strings are immutable");测试见 tests/sdk_tests/std/string.test.w。
4.5split(separator: str): MutArray<str>
按分隔符将字符串拆分为可变字符串数组MutArray<str>。特别地,传入空字符串""作为分隔符时,会按单个字符逐个拆分。
split(separator: str): MutArray<str>assert("hello;wing".split(";").at(0) == "hello"); assert("hello;wing".split(";").at(1) == "wing"); assert("hello wing".split(" ").at(0) == "hello"); // 空分隔符按字符拆分 assert("hello wing".split("").length == 10); assert("hello wing".split("").at(0) == "h"); assert("hello wing".split("").at(1) == "e");测试见 tests/sdk_tests/std/string.test.w。split常与Json.stringify配合输出结构化结果(见下文实战示例)。
五、静态方法fromJson:从Json安全转换字符串
5.1 签名与语义
String类还提供唯一的静态方法,用于把Json值安全转换为强类型字符串:
str.fromJson(json: Json, options?: JsonValidationOptions): strjson(必填):要转换为字符串的Json值。options(可选):JsonValidationOptions类型,来自 packages/@winglang/sdk/src/std/json.ts,目前仅包含一个字段:
| 字段 | 类型 | 说明 |
|---|---|---|
unsafe | bool? | 设为true时跳过运行时类型校验(可能引发运行时错误) |
5.2 为什么需要fromJson:动态 JSON 的类型安全
在 Wing 中,仅当Json字面量在程序中静态可见时,才能直接赋值给str变量;对于来自外部(如http.get()的响应)的动态Json,直接赋值会编译报错。此时必须使用fromJson()进行带运行时校验的转换。参见 docs/api/05-language-reference.md:
let jsonString = Json "hello"; let myStr = str.fromJson(jsonString);5.3 运行时校验与失败行为
fromJson的底层实现位于 packages/@winglang/sdk/src/std/string.ts:它通过JsonSchema构造type: "string"的 schema 并对输入json执行校验,校验不通过时抛出错误。语言参考给出的失败示例:
str.fromJson(Json 123); // RUNTIME ERROR: unable to parse number `123` as a string.测试 tests/sdk_tests/std/string.test.w 中定义了错误信息常量PARSE_ERROR = "unable to parse string",并断言传入Json 123会抛出包含该文本的异常:
let PARSE_ERROR = "unable to parse string"; assert(str.fromJson(Json "Hello") == "Hello"); // str.fromJson(Json 123); // 抛出 "unable to parse string"num.fromJson、bool.fromJson等其余基础类型同理(见 tests/valid/json_static.test.w 中str.fromJson(jsonOfMany.get("b")) == "hello"的用法)。
5.4 相关的tryFromJson与unsafe
fromJson校验失败会抛异常;若希望以可选值方式处理失败,语言参考介绍了配套的tryFromJson()方法,返回str?,可与??配合提供默认值(docs/api/05-language-reference.md):
let s = str.tryFromJson(myJson) ?? "invalid string";当确信Json值类型正确、希望跳过运行时校验换取性能时,可传入unsafe: true:
str.fromJson(Json 10, unsafe: true); // 跳过校验,自行承担类型风险上述用法在 tests/valid/struct_from_json.test.w 与语言参考的 schema validation 章节中均有体现。
六、实战示例:完整运行与预期输出
官方 by-example 章节 docs/by-example/21-string-functions.md 给出了一个覆盖本文多数 API 的可直接运行的main.w,其自动化生成版本位于 tests/doc_examples/valid/21-string-functions.md_example_1/main.w:
log("test".contains("es")); log("test".length); log("test".startsWith("te")); log("test".endsWith("st")); log("test".indexOf("e")); let x = ["a", "b"]; log(x.join("-")); log("foo".replace("o", "0")); log("foo".replaceAll("o", "0")); log(Json.stringify(("a-b-c-d-e".split("-")))); log("TEST".lowercase()); log("test".uppercase());在本地通过 Wing 控制台运行(wing it),预期输出:
true 4 true true 1 a-b f0o f00 ["a","b","c","d","e"] test TEST注意上例中"test".indexOf("e")返回1(首个e的位置),以及split("-")的结果经Json.stringify输出为 JSON 数组形式。
七、源码视角:@macro与 JS 原生方法的映射
从 packages/@winglang/sdk/src/std/string.ts 可以看到,String类的大多数实例方法并非真正实现,而是通过 JSDoc 中的@macro指令在编译期展开为 JavaScript 原生字符串方法,形成一个轻量、无运行时开销的映射层:
| Wing 方法 | 编译期展开为(JS) |
|---|---|
at | 带越界检查的自定义展开(见 3.1) |
contains | $self$.includes($args$) |
endsWith | $self$.endsWith($args$) |
indexOf | $self$.indexOf($args$) |
lowercase | $self$.toLocaleLowerCase() |
uppercase | $self$.toLocaleUpperCase() |
replace | $self$.replace(...$args$) |
replaceAll | $self$.replaceAll(...$args$) |
这一点解释了contains与indexOf的大小写敏感行为、indexOf未命中返回-1、replace只替换首处等语义,均与 JS 原生String对象保持一致。源码注释同时说明:该类的目的是为 Wing 编译器提供str类型的 JSII 子集,通常不应被用户直接实例化消费。
八、方法速查总表
以下为 docs/api/04-standard-library/std/string.md 中定义的完整 API 一览:
| 类别 | 名称 | 签名 | 说明 |
|---|---|---|---|
| 属性 | length | length: num | 字符串长度 |
| 查询 | contains | contains(searchString: str): bool | 是否包含子串(大小写敏感) |
| 查询 | startsWith | startsWith(searchString: str): bool | 是否以子串开头 |
| 查询 | endsWith | endsWith(searchString: str): bool | 是否以子串结尾 |
| 查询 | indexOf | indexOf(searchString: str): num | 首次出现索引,未找到返回 -1 |
| 提取 | at | at(index: num): str | 取指定索引字符,支持负索引,越界抛错 |
| 提取 | substring | substring(indexStart: num, indexEnd?: num): str | 截取子串,结束索引可选 |
| 变换 | replace | replace(searchString: str, replaceString: str): str | 替换首次出现的子串 |
| 变换 | replaceAll | replaceAll(searchString: str, replaceString: str): str | 替换全部出现的子串 |
| 变换 | lowercase | lowercase(): str | 转为小写(本地化规则) |
| 变换 | uppercase | uppercase(): str | 转为大写(本地化规则) |
| 变换 | trim | trim(): str | 移除首尾空白 |
| 变换 | concat | concat(strN: str): str | 拼接字符串 |
| 变换 | split | split(separator: str): MutArray<str> | 按分隔符拆分(空串按字符拆) |
| 静态 | fromJson | str.fromJson(json: Json, options?: JsonValidationOptions): str | 从Json安全转换并校验 |
延伸阅读
- API 参考原文:docs/api/04-standard-library/std/string.md
- 实战示例与输出:docs/by-example/21-string-functions.md
- 语言参考(
str类型与字符串字面量、fromJson校验模型):docs/api/05-language-reference.md - 标准库源码实现(
String类与@macro):packages/@winglang/sdk/src/std/string.ts - 校验选项定义(
JsonValidationOptions.unsafe):packages/@winglang/sdk/src/std/json.ts - SDK 测试套件(覆盖全部方法与边界行为):tests/sdk_tests/std/string.test.w
- 语言级字符串语义测试:tests/valid/std_string.test.w
- 编程语言
- 编译器
- 云原生
- 语言运行时
【免费下载链接】wing
A programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡
相关推荐
rust-by-practice 复合类型实战:彻底掌握 Rust 字符串(str / &str / String)的类型体系、转换与 UTF-8 操作
rust by practice 复合类型实战:彻底掌握 Rust 字符串(str / &str / String)的类型体系、转换与 UTF 8 操作 本指南
文档教程示例工程lamda(FIRERPA):一个 Python 客户端跑通 Android UI 自动化与一键抓包
lamda(FIRERPA):一个 Python 客户端跑通 Android UI 自动化与一键抓包 lamda 是面向 Android 的全栈设备控制平台:服
GUI自动化逆向工程RPAMCP 服务开发工具pybind11 字符串与编码转换完全指南:str / bytes / std::string / wchar_t / string_view 全链路解析
pybind11 字符串与编码转换完全指南:str / bytes / std::string / wchar_t / string_view 全链路解析 在
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考