【问题标题】:What is the syntax for a multiline string literal?多行字符串文字的语法是什么?
【发布时间】:2015-06-11 13:32:49
【问题描述】:

我很难弄清楚字符串语法在 Rust 中是如何工作的。具体来说,我正在尝试弄清楚如何制作多行字符串。

【问题讨论】:

标签: string rust


【解决方案1】:

所有字符串字面量都可以分成几行;例如:

let string = "line one
line two";

是一个两行字符串,与"line one\nline two" 相同(当然也可以直接使用\n 换行符转义)。如果您出于格式化原因只想将字符串拆分为多行,则可以使用 \ 转义换行符和前导空格;例如:

let string = "one line \
    written over \
    several";

"one line written over several"相同。

如果您想在字符串中添加换行符,您可以在 \: 之前添加它们:

let string = "multiple\n\
              lines\n\
              with\n\
              indentation";

"multiple\nlines\nwith\nindentation";一样

【讨论】:

  • 如果只有可读性是问题,我想添加 concat!() 宏来完成给定的选项 (doc.rust-lang.org/std/macro.concat.html)
  • 如果我想在下一行保留空格而不是在前一行的反斜杠之前怎么办?这是可能的还是因为它被认为是缩进的一部分而总是被“吃掉”?
  • @theberzi,是的,保留空格的唯一方法是将其放在 \\ 之前,因为所有前导空格都在下一行被吃掉。
  • 看起来尾随反斜杠仅删除下一行的前导空格字符,而不是第一个字符之前的所有空格(例如,如果您使用制表符缩进,它们将不会被删除)。
【解决方案2】:

如果您想做一些更长的事情,可能包含也可能不包含引号、反斜杠等,请使用raw string literal notation

let shader = r#"
    #version 330

    in vec4 v_color;
    out vec4 color;

    void main() {
        color = v_color;
    };
"#;

如果字符串中有双引号和哈希符号序列,则可以将任意数量的哈希表示为分隔符:

let crazy_raw_string = r###"
    My fingers #"
    can#"#t stop "#"" hitting
    hash##"#
"###;

【讨论】:

  • 但是...如果您不希望结果中出现换行符,您只需要转义换行符,而原始字符串对此无济于事。
  • 如果您不关心换行符(例如当您嵌入与着色器一样与换行符无关的代码时,原始字符串只会阻止您必须在每行的末尾添加一个“\”)和内核),或者正如您所提到的,当换行符实际上是必要的时。它只是让您更容易嵌入您可能想要编辑的代码,而不必在每行末尾使用“\”。就是这样。
  • 如果你想要(或不介意)结果字符串中的换行符,普通的双引号字符串会做得很好,如其他示例所示。如果你想避免换行,原始字符串是不好的。只有当文本包含引号、反斜杠等时,它们才真正有帮助 - 这可能发生在嵌入式源代码中。
  • 我明白你现在的情况,你是绝对正确的。
  • 这将有助于显示打印这些字符串的输出。从答案本身我无法判断换行符会发生什么,以及如何处理缩进。
【解决方案3】:

Huon's answer 是正确的,但如果缩进让您感到困扰,请考虑使用Indoc,它是缩进多行字符串的程序宏。它代表“缩进文档”。它提供了一个名为 indoc!() 的宏,它接受多行字符串文字并取消缩进,因此最左边的非空格字符位于第一列。

let s = indoc! {"
    line one
    line two
"};

结果是"line one\nline two\n"

相对于文档中最左边的非空格字符保留空白,因此下面的第二行相对于第一行缩进了 3 个空格:

let s = indoc! {"
    line one
       line two
"};

结果是"line one\n line two\n"

【讨论】:

  • 啊!非常感谢!我正要创建自己的问题,特别是关于使用缩进执行多行字符串文字的最佳方法,当我在这里偶然发现您的答案时,这也很好地保留了代码缩进!作为参考,我创建了一个 rust playground,其中列出了我提出的各种选项以及它们的相对缺点:play.rust-lang.org/…
【解决方案4】:

如果您想在代码中缩进多行文本:

let s = "first line\n\
    second line\n\
    third line";

println!("Multiline text goes next:\n{}", s);

结果如下:

Multiline text goes next:
first line
second line
third line

【讨论】:

  • 明确用散文说明哪段代码对这种行为很重要。
  • 现在,这似乎没有向the accepted answer 添加任何新内容,其中指出:可以使用\n 换行符转义 [...] 你可以转义换行符和前导带有{backslash} 的空格。 (在注释中的代码中输入反斜杠非常困难,看来。)
  • 此评论建议一种将已接受答案中的两点结合起来的方法:如何生成多行字符串,在代码中编写为多行,但同时允许——出于文体或易读性的原因——在代码中获得自己的缩进,而该缩进不以最终字符串结尾。文中没有说得很清楚,但这是一个常见的用例,因此是一个有价值的建议恕我直言。 (请参阅 dtolnay 的答案以获取此板条箱版本。)
  • 回复:Dato 的评论:“请参阅 dtolnay 的答案以获取此板条箱版本”:要清楚,Indoc 与此处给出的示例不同,因为 indoc! 保留缩进。
【解决方案5】:

如果您想在不使用外部 crate 的情况下对带有换行符的多行字符串中的空格进行精细控制,您可以执行以下操作。示例取自我自己的项目。

impl Display for OCPRecData {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "OCPRecData {{\n\
            \x20   msg: {:?}\n\
            \x20   device_name: {:?}\n\
            \x20   parent_device_name: {:?}\n\
        }}", self.msg, self.device_name, self.parent_device_name)
    }
}

结果

OCPRecData {
    msg: Some("Hello World")
    device_name: None
    parent_device_name: None
}
  • \n\ 在每个代码行末尾创建一个换行符在适当的位置,并丢弃这行代码中的更多空格
  • \x20(十六进制;十进制中的 32)是一个 ASCII 空格,是该行字符串中要保留的第一个空格的指示符
  • \x20\x20\x20\x20\x20 效果一样

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多