Reputation: 568
starting from this C# example:
string myStringFormat = "I want to surround string {0} with {{ and }}";
string myStringArgs = "StringToSurround";
string myFinalString = string.Format(myStringFormat, myStringArgs);
I'd like to know if there is a quick and simple way to distinguish between escape character/sequence and arguments for curly braces/brackets.
The reasons why I am asking this are:
+] I want to provide some logging functionality and I don't want to require users to be aware of the double curly braces/brackets escape rule
+] I want to be very fast in doing this distinction for performance requirements
Currently the only solution I can think about is to scan the string looking for curly braces/brackets and do some check (number parsing) on subsequent characters. Probably regex can be helpful but I cannot find a way to use them in this scenario.
Btw, the final situation I'd like to achieve is user being allowed to this without getting exceptions:
string myStringFormat = "I want to surround string {0} with { and }";
string myStringArgs = "StringToSurround";
//string myFinalString = string.Format(myStringFormat, myStringArgs); throwing exception
string myFinalString = MyCustomizedStringFormat(myStringFormat, myStringArgs);
EDIT:
sorry the word "surround" was tricky and misleading, please consider this example:
string myStringFormat = "I want to append to string {0} these characters {{ and }}";
string myStringArgs = "StringToAppendTo";
string myFinalString = string.Format(myStringFormat, myStringArgs);
giving output
I want to append to string StringToAppendTo these characters { and }
Upvotes: 1
Views: 521
Reputation: 17115
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:
@"{{\d+}}"
m[i].Value.Substring(1, m[i].Value.Length - 2)
instead of args[i]
Upvotes: 1