Remove single trailing newline from String without cloning
A cross-platform way of stripping a single trailing newline without reallocating the string is this:
fn trim_newline(s: &mut String) {
if s.ends_with('\n') {
s.pop();
if s.ends_with('\r') {
s.pop();
}
}
}
This will strip either "\n"
or "\r\n"
from the end of the string, but no additional whitespace.
with strip_suffix
This removes one trailing \r\n
or \n
:
fn strip_trailing_newline(input: &str) -> &str {
input
.strip_suffix("\r\n")
.or(input.strip_suffix("\n"))
.unwrap_or(input)
}
If there are multiple newlines, only the last one is stripped off.
If there is no newline at the end of the string, the string is unchanged.
Some tests:
#[test]
fn strip_newline_works(){
assert_eq!(strip_trailing_newline("Test0\r\n\r\n"), "Test0\r\n");
assert_eq!(strip_trailing_newline("Test1\r\n"), "Test1");
assert_eq!(strip_trailing_newline("Test2\n"), "Test2");
assert_eq!(strip_trailing_newline("Test3"), "Test3");
}
A more generic solution than the accepted one, that works with any kind of line ending:
fn main() {
let mut s = "hello\r\n".to_string();
let len_withoutcrlf = s.trim_right().len();
s.truncate(len_withoutcrlf);
assert_eq!("hello", &s);
}
You can use String::pop
or String::truncate
:
fn main() {
let mut s = "hello\n".to_string();
s.pop();
assert_eq!("hello", &s);
let mut s = "hello\n".to_string();
let len = s.len();
s.truncate(len - 1);
assert_eq!("hello", &s);
}