Как экранировать фигурные скобки в строке форматирования в Rust?
Экранирование фигурных скобок через удвоение
В Rust для вывода буквальных фигурных скобок в строках форматирования используется простое правило: удвойте скобку.
{{ выведет одну открывающую скобку {, а }} — одну закрывающую }.
Это работает во всех макросах семейства format!: format!, println!, write!, print! и т.д.
fn main() {
// Простейший пример: вывод скобок без подстановки
println!("{{Hello}}"); // Выведет: {Hello}
// Комбинация с подстановкой значения
let value = 42;
println!("{{ значение: {} }}", value); // Выведет: { значение: 42 }
// Именованные аргументы
println!("{{x: {x}}}", x = 10); // Выведет: {x: 10}
// JSON-подобный вывод
let key = "name";
let val = "Alice";
println!(r#"{{"{}": "{}"}}"#, key, val); // Выведет: {"name": "Alice"}
}
Правила экранирования
- Две открывающие скобки
{{→ одна{ - Две закрывающие скобки
}}→ одна} - Если вам нужно
{{или}}как текст — используйте{{{{и}}}}(четыре скобки дадут две)
Пример с вложенным форматированием
Предположим, вы хотите сгенерировать строку, где количество фигурных скобок зависит от данных. Например, создание шаблона LaTeX или JSON с динамическими ключами.
fn generate_json(key: &str, value: &str) -> String {
format!(r#"{{"{}": "{}"}}"#, key, value)
}
fn main() {
let json = generate_json("status", "ok");
println!("{}", json); // {"status": "ok"}
// Если нужны двойные фигурные скобки (например, для шаблонизатора)
let template = format!("{{{{ {} }}}}", "variable");
println!("{}", template); // {{ variable }}
}
Работа с write! и writeln!
Правило удвоения работает и для макросов, записывающих в поток. Пример с write!:
use std::fmt::Write;
fn main() {
let mut output = String::new();
write!(&mut output, "{{x: {}, y: {}}}", 10, 20).unwrap();
println!("{}", output); // {x: 10, y: 20}
}
Почему не работает обратный слеш?
В Rust строки форматирования не поддерживают escape-последовательности в стиле C (\{).
Обратный слеш в форматной строке трактуется буквально или как часть спецификатора формата (например, \n для новой строки).
Экранирование фигурных скобок реализовано именно через удвоение, так как это проще парсить и не конфликтует с другими правилами.
Советы для новичков
- Если вы пишете много скобок подряд, используйте сырые строки (
r#"..."#) — они упрощают чтение, но не отменяют правила удвоения внутри форматной строки. - Для сложных шаблонов рассмотрите использование крейта
serde_jsonдля JSON или специализированных шаблонизаторов. - Помните:
{{и}}— это единственный способ. Не пытайтесь экранировать через\или HTML-сущности.
Если вам нужно вывести ровно одну фигурную скобку — используйте {{ или }}.
Для двух — {{{{ или }}}} и так далее. Это интуитивно понятно после пары примеров.
fn main() {
// Демонстрация всех вариантов
println!("Одна скобка: {{ и }}"); // Одна скобка: { и }
println!("Две скобки: {{{{ и }}}}"); // Две скобки: {{ и }}
// Реальный пример: математическая формула
let a = 3;
let b = 4;
println!("{{ {} + {} = {} }}", a, b, a + b); // { 3 + 4 = 7 }
}
<<Альтернативный подход: конкатенация строк
Если вам неудобно запоминать правила удвоения скобок, или вы имеете дело с очень сложным форматированием, можно просто использовать конкатенацию строк с помощью оператора + или макроса concat!. Этот подход полностью обходит механизм форматирования.
fn main() {
let value = 42;
// Вариант 1: конкатенация через +
let result = "{ значение: ".to_string() + &value.to_string() + " }";
println!("{}", result); // { значение: 42 }
// Вариант 2: макрос concat! (только для строковых литералов)
let key = "x";
let result2 = concat!("{", key, ": ", "10", "}");
println!("{}", result2); // {x: 10}
// Вариант 3: format! без экранирования (передаём скобки как обычные строки)
let left = "{";
let right = "}";
println!("{} {} {}", left, value, right); // { 42 }
}
Когда это полезно?
- При динамическом построении строк с переменным количеством скобок.
- В коде, где читаемость важнее производительности (конкатенация может быть медленнее
format!). - При работе с текстом, содержащим много уровней вложенных скобок (например, генерация LaTeX).
Однако учтите, что concat! работает только на этапе компиляции и принимает исключительно строковые литералы. Для переменных используйте format! с экранированием или конкатенацию через +.
// Пример для LaTeX: \frac{1}{2}
let numerator = 1;
let denominator = 2;
// Через format! с экранированием:
println!("\\frac{{{}}}{{{}}}", numerator, denominator); // \frac{1}{2}
// Через конкатенацию:
println!("\\frac{"
+ &numerator.to_string()
+ "}{"
+ &denominator.to_string()
+ "}"); // \frac{1}{2}
Ответов пока нет.
Войдите чтобы оставить ответ