Rust中带续行符的多行字符串为何丢失预期行首空白?
问题根源
- Rust 普通字符串字面量中,行尾反斜杠
\作为续行符的语义是:跳过反斜杠与下一个非空白字符之间的所有空白,包括当前行的换行符、后续行的全部前导空格。 - 非工作版本的字符串写法中,开引号后紧跟行尾
\,下一行开头的两个空格恰好处于续行符与下一个非空白字符(╷)的跳过区间,因此被直接移除,导致输出丢失开头空格。 - 工作版本字符串没有该问题,是因为其下一行开头没有额外空格,续行符的跳过操作不影响实际输出。
解决方案
方案1:保留原代码缩进结构,用转义序列显式声明前置空格
不需要修改开引号后加 \ 的缩进写法,将被跳过的前导空格用ASCII空格的十六进制转义 \x20 替代即可:
const NON_WORKING: &str = "\ \x20\x20╷ │ ╶─┼╴ │ ╶─┼╴ ╶─┼╴ │ ╵ ";
原理:续行符 \ 后遇到的第一个非空白字符是 \x20 的反斜杠,仅会跳过两者之间的换行符,\x20 会被解析为实际空格,不会被吃掉。
方案2:使用原始字符串,编译期修剪开头换行
放弃行尾续行符,改用原始字符串避免转义歧义,前导空格会被完整保留,仅需去掉字符串开头多余的换行:
const NON_WORKING: &str = r#" ╷ │ ╶─┼╴ │ ╶─┼╴ ╶─┼╴ │ ╵ "#.trim_start_matches('\n');
注:str::trim_start_matches 从 Rust 1.64 开始为可在编译期调用的 const fn,可直接用于常量定义。
方案3:直接将首行内容跟在开引号后
如果不介意首行内容与代码缩进对齐,可以直接去掉开引号后的行尾 \,将首行空格直接写在开引号后,无额外转义成本:
const NON_WORKING: &str = " ╷ │ ╶─┼╴ │ ╶─┼╴ ╶─┼╴ │ ╵ ";
内容的提问来源于stack exchange,提问作者Netwave
相关产品推荐
相关产品推荐

