How to Escape Braces (Curly Brackets) in a Format String in .Net

How to escape braces (curly brackets) in a format string in .NET

For you to output foo {1, 2, 3} you have to do something like:

string t = "1, 2, 3";
string v = String.Format(" foo {{{0}}}", t);

To output a { you use {{ and to output a } you use }}.

Or now, you can also use C# string interpolation like this (a feature available in C# 6.0)

Escaping brackets: String interpolation $(""). It is new feature in C# 6.0.

var inVal = "1, 2, 3";
var outVal = $" foo {{{inVal}}}";
// The output will be: foo {1, 2, 3}

Why escape brackets (curly braces) in a format string in .NET is '{{' or '}} not '\{' or '\}'

Format strings are interpreted during the runtime (not during compile time)

If C# would allow to enter \{ or \} it would be stored in the string as { and } respectively. The string.Format function then reads this string to decide if a formatting instruction is to be interpreted, e.g. {0}. Since the \{ resulted in { character in the string, the String.Format function could not decide that this is to be taken as a format instruction or as literal {. So, string.Format treats {{ as literal {. Analogous }} for }.

Escaping in C#:

- character literal escaping:   e.g. '\'', '\n', '\u20AC' (the Euro € currency sign), '\x9' (equivalent to \t))
- literal string escaping: e.g. "...\t...\u0040...\U000000041...\x9..."
- verbatim string escaping: e.g. @"...""..."
- string.Format escaping: e.g. "...{{...}}..."
- keyword escaping: e.g. @if (for if as identifier)
- identifier escaping: e.g. i\u0064 (for id)

Escape curly brace '{' in String.Format

Use double braces {{ or }} so your code becomes:

sb.AppendLine(String.Format("public {0} {1} {{ get; private set; }}", 
prop.Type, prop.Name));

// For prop.Type of "Foo" and prop.Name of "Bar", the result would be:
// public Foo Bar { get; private set; }

escape curly braces { in a string to support String.Format

How about this:

string input = "Hello {0}, please refer for more information {or contact us at: XXXX}";
Regex rgx = new Regex("(\\{(?!\\d+})[^}]+})");
string replacement = "{$1}";
string result = rgx.Replace(input, replacement);

Console.WriteLine("String {0}", result);

// Hello {0}, please refer for more information {{or contact us at: XXXX}}

... assuming that the only strings that should not be escaped are of format {\d+}.

There are two caveats here. First, we may encounter already-escaped curvy braces - {{. Fix for it is more-o-less easy: add more lookarounds...

Regex rgx = new Regex("(\\{(?!\\d+})(?!\\{)(?<!\\{\\{)[^}]+})");

... in other words, when trying to replace a bracket, make sure it's a lonely one. )

Second, formats themselves may not be so simple - and as the complexity of those that actually may be present in your strings grows, so does the regex's one. For example, this little beasty won't attempt to fix format string that start with numbers, then go all the way up to } symbol without any space in between:

Regex rgx = new Regex("(\\{(?!\\d\\S*})(?!\\{)(?<!\\{\\{)[^}]+})");

As a sidenote, even though I'm the one of those people that actually like to have two problems (well, sort of), I do shudder when I look at this.

UPDATE: If, as you said, you need to escape each single occurrence of { and }, your task is actually a bit easier - but you will need two passes here, I suppose:

Regex firstPass = new Regex("(\\{(?!\\d+[^} ]*}))");
string firstPassEscape = "{$1";
...
Regex secondPass = new Regex("((?<!\\{\\d+[^} ]*)})");
string secondPassEscape = "$1}";

How to escape curly braces in Json string in C# string formatter

Use double curly braces
Escape curly brace '{' in String.Format

Oh, and you will need to add quotes around you placeholders:

string formater = @"{{'attachments':[{{'title':'New item added','title_link':'{0}','text':'{1}','image_url':'{2}','color':'#764FA5'}}]}}";
string myJson = String.Format(formater, product.Url, "text", product.ImageUrl);

How do I escape a brace in an interpolated string, after a brace with a format string?

Please have a look at Escaping Braces documentation

For example, consider the format item "{{{0:D}}}", which is intended
to display an opening brace, a numeric value formatted as a decimal
number, and a closing brace. However, the format item is actually
interpreted in the following manner: The first two opening braces
("{{") are escaped and yield one opening brace. The next three
characters ("{0:") are interpreted as the start of a format item. The
next character ("D") would be interpreted as the Decimal standard
numeric format specifier, but the next two escaped braces ("}}") yield
a single brace. Because the resulting string ("D}") is not a standard
numeric format specifier, the resulting string is interpreted as a
custom format string that means display the literal string "D}".

This is exactly your case, you are getting incorrect format specifier as a result.

For you code you can try to use the old string.Format

string.Format("{0}{1:d}{2}", "{", DayOfWeek.Friday, "}");

C# - Auto-detect Escape and Argument curly braces in string.Format

Use this Regex to find the Argument substrings:

{\d+}

This regex escapes {} {1a} etc. and only chooses {1} {11} etc.


Now you need to handle either Arguments (replace them with their values) or the Escaped curly braces (replace them with double braces). The choice is yours and it depends on the number of occurrences of each case. (I chose to replace arguments in my code below)

Now you need to actually replace the characters. Again the choice is yours to use a StringBuilder or not. It depends on the size of your input and the number of replacements. In any case I suggest StringBuilder.

var m = Regex.Matches(input, @"{\d+}");
if (m.Any())
{
// before any arg
var sb = new StringBuilder(input.Substring(0, m[0].Index));

for (int i = 0; i < m.Count; i++)
{
// arg itself
sb.Append(args[i]);

// from right after arg
int start = m[i].Index + m[i].Value.Length;

if (i < m.Count - 1)
{
// until next arg
int length = m[i + 1].Index - start;
sb.Append(input.Substring(start, length));
}
else
// until end of input
sb.Append(input.Substring(start));
}
}

I believe this is the most robust and cleanest way to do it,and it does not have any performance (memory or speed) issues.


Edit

If you don't have access to args[] then you can first replace {/} with {{/}} and then simply do these modifications to the code:

  1. use this pattern: @"{{\d+}}"
  2. write m[i].Value.Substring(1, m[i].Value.Length - 2) instead of args[i]

Escaped curly brace in string.format gets lost. Possible C# bug?

From Escaping Braces section on Composite Formatting;

Opening and closing braces are interpreted as starting and ending a
format item. Consequently, you must use an escape sequence to display
a literal opening brace or closing brace. Specify two opening braces
("{{") in the fixed text to display one opening brace ("{"), or two
closing braces ("}}") to display one closing brace ("}"). Braces in a
format item are interpreted sequentially in the order they are
encountered. Interpreting nested braces is not supported.

The way escaped braces are interpreted can lead to unexpected results.
For example, consider the format item "{{{0:D}}}", which is intended
to display an opening brace, a numeric value formatted as a decimal
number, and a closing brace. However, the format item is actually
interpreted in the following manner:

  • The first two opening braces ("{{") are escaped and yield one opening brace.

  • The next three characters ("{0:") are interpreted as the start of a format item.

  • The next character ("D") would be interpreted as the Decimal standard numeric format specifier, but the next two escaped braces
    ("}}") yield a single brace. Because the resulting string ("D}") is
    not a standard numeric format specifier, the resulting string is
    interpreted as a custom format string that means display the literal
    string "D}".

  • The last brace ("}") is interpreted as the end of the format item.

  • The final result that is displayed is the literal string, "{D}". The numeric value that was to be formatted is not displayed.


One way to write your code to avoid misinterpreting escaped braces and
format items is to format the braces and format item separately
.

So you should use it as;

string result = string.Format(@"{0}{1:G};{2:G}{3}", "{", "foo", "bar", "}");


Related Topics



Leave a reply



Submit