339

I'm having a hard time figuring out how string syntax works in Rust. Specifically, I'm trying to figure out how to make a multiple line string.

kmdreko
  • 42,554
  • 6
  • 57
  • 106
Dumbapples
  • 3,879
  • 3
  • 14
  • 10
  • 2
    Possible duplicate of [How do I write a multi-line string in Rust?](http://stackoverflow.com/questions/15265198/how-do-i-write-a-multi-line-string-in-rust) – Jo Liss Feb 27 '17 at 13:48
  • It's a bit weird that the older question is marked as a duplicate of a newer one. Shouldn't this be the other way around? – BinaryButterfly Aug 27 '22 at 21:59
  • @BinaryButterfly I think it's because this question has gotten much more attention and has clearer answers – TheTechRobo the Nerd Mar 17 '23 at 13:07

5 Answers5

428

All string literals can be broken across several lines; for example:

let string = "line one
line two";

is a two line string, the same as "line one\nline two" (of course one can use the \n newline escape directly too). If you wish to just break a string across multiple lines for formatting reasons you can escape the newline and leading whitespace with a \; for example:

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

is the same as "one line written over several".

If you want linebreaks in the string you can add them before the \:

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

It's the same as "multiple\nlines\nwith\nindentation";

Rich Kadel
  • 135
  • 2
  • 6
huon
  • 94,605
  • 21
  • 231
  • 225
  • 22
    If only readability is the issue, I would like to add the `concat!()` macro to complete the given options (https://doc.rust-lang.org/std/macro.concat.html) – hakononakani Sep 25 '19 at 17:07
  • What if I want to keep the space on the next line instead of before the backslash on the previous one? Is that possible or will it always be "eaten" because it's considered part of the indentation? – theberzi Sep 30 '21 at 20:13
  • 3
    @theberzi, yes, the only way to keep whitespace is to place it before the \\ as all leading whitespace is eaten on the next line. – huon Oct 01 '21 at 05:30
  • It looks like the trailing backslash only removes leading space characters on the next line, not all whitespace up to the first character (for instance, if you indent with tabs, they won't be removed). – BallpointBen Dec 17 '21 at 03:00
246

In case you want to do something a bit longer, which may or may not include quotes, backslashes, etc., use the raw string literal notation:

let shader = r#"
    #version 330

    in vec4 v_color;
    out vec4 color;

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

Outputs:

    #version 330

    in vec4 v_color;
    out vec4 color;

    void main() {
        color = v_color;
    };

Playground link


If you have sequences of double quotes and hash symbols within your string, you can denote an arbitrary number of hashes as a delimiter:

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

Which outputs:

    My fingers #"
    can#"#t stop "#"" hitting
    hash##"#
Jing
  • 1,881
  • 2
  • 15
  • 13
c0g
  • 2,665
  • 1
  • 13
  • 5
  • 3
    But... you only need to escape newlines if you don't want newlines in the result, and raw strings don't help with that. – poolie Jul 04 '16 at 00:42
  • 2
    Raw strings just prevent you from having to add a '\' at the end of every line if you don't care about the newlines (such as when you are embedding code which is newline agnostic like shaders and kernels) or, as you alluded to, when the newlines are actually necessary. It just makes it easier to embed code which you might want to edit and not have to hassle with the '\' at the end of each line. That's all. – c0g Jul 07 '16 at 05:03
  • 2
    If you want (or don't mind) newlines in the resulting string, plain double quoted strings will do perfectly well, as shown in the other examples. If you want to avoid newlines, raw strings are no good. They really only help if the text includes quotes, backslashes, etc - as may happen in embedded source. – poolie Jul 08 '16 at 15:55
  • 2
    I see what you're getting at now and you're absolutely right. – c0g Jul 11 '16 at 23:40
  • 13
    It would help to show the output of printing these strings. From the answer itself I can't tell what will happen with newlines, and how indentation is handled. – bluenote10 Jan 17 '20 at 07:09
  • I’ve went ahead and downvoted because the answer is too vague for my tastes. As mentioned, there’s no mention of how leading indentation is handled. – rv.kvetch Feb 12 '22 at 22:52
115

Huon's answer is correct but if the indentation bothers you, consider using Indoc which is a procedural macro for indented multi-line strings. It stands for "indented document." It provides a macro called indoc!() that takes a multiline string literal and un-indents it so the leftmost non-space character is in the first column.

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

The result is "line one\nline two\n".

Whitespace is preserved relative to the leftmost non-space character in the document, so the following has line two indented 3 spaces relative to line one:

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

The result is "line one\n line two\n".

dtolnay
  • 9,621
  • 5
  • 41
  • 62
  • 7
    Ah! Thanks so much for this! I was about to create my own question, specifically about the best way to do a multiline string literal with indentation, that also that preserved code-indentation nicely, when I stumbled across your answer here! For reference, I created a rust playground which lists various options I came up with, and their relative shortcomings: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c9ca0febb5f154e30811806873e38716 – Paul Molodowitch Nov 22 '20 at 10:59
  • 2
    This exact problem bugs me in pretty much every language I ever use, and there's always some different way around it. Gotta love being able to use such a friendly macro! TY. – DexieTheSheep Jan 01 '23 at 03:27
  • if you need string interpolation, see [indoc::formatdoc!](https://rustjobs.dev/blog/formatting-multiline-strings-with-interpolation-in-rust/) – ecoe Jul 25 '23 at 19:07
20

If you want to have fine granular control over spaces in multiline strings with linebreaks without using an external crate you can do the follwing. Example taken from my own project.

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)
    }
}

Results in

OCPRecData {
    msg: Some("Hello World")
    device_name: None
    parent_device_name: None
}
  • \n\ at each code line end creates a line break at the proper position and discards further spaces in this line of code
  • \x20 (hex; 32 in decimal) is an ASCII space and an indicator for the first space to be preserved in this line of the string
  • \x20\x20\x20\x20 and \x20 have the same effect
phip1611
  • 5,460
  • 4
  • 30
  • 57
12

In case you want to indent multiline text in your code:

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

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

The result will be the following:

Multiline text goes next:
first line
second line
third line
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Igor
  • 600
  • 6
  • 13
  • 2
    Please *explicitly* state, using prose, what piece of the code is important to this behavior. – Shepmaster Jan 07 '19 at 18:55
  • 1
    Right now, this appears to not add anything new to [the accepted answer](https://stackoverflow.com/a/29483453/155423), which states: *one can use the `\n` newline escape [...] you can escape the newline and leading whitespace with a `{backslash}`*. (it's very hard to type a backslash in code in a comment, it appears.) – Shepmaster Jan 07 '19 at 18:57
  • 2
    This comment is suggesting a way to combine the two points in the accepted answer: how you can produce a multi-line string, written as multiples lines in code, but that at the same time is allowed to —for stylistic or legibility reason— get its own indentation in code, without this indentation ending in the final string. It’s not made very clear in the text, but it’s a common use case and thus a valuable suggestion imho. (See the answer by dtolnay for the crate version of this.) – Dato Jan 09 '19 at 22:43
  • Re: Dato's comment: "See the answer by dtolnay for the crate version of this": to be clear, [Indoc](https://docs.rs/indoc) is different that the example given here, since `indoc!` preserves indentation. – David J. Feb 28 '21 at 17:50