views:

212

answers:

5

Hiho everyone! :)

I have an application, in which the user can insert a string into a textbox, which will be used for a String.Format output later. So the user's input must have a certain format:

I would like to replace exactly one placeholder, so the string should be of a form like this: "Text{0}Text". So it has to contain at least one '{0}', but no other statement between curly braces, for example no {1}.

For the text before and after the '{0}', I would allow any characters.

So I think, I have to respect the following restrictions: { must be written as {{, } must be written as }}, " must be written as \" and \ must be written as \.

Can somebody tell me, how I can write such a RegEx? In particular, can I do something like 'any character WITHOUT' to exclude the four characters ( {, }, " and \ ) above instead of listing every allowed character?

Many thanks!! Nikki:)

+1  A: 

It sounds like you're looking for the [^CHARS_GO_HERE] construct. The exact regex you'd need depends on your regex engine, but it would resemble [^({})].

Check out the "Negated Character Classes" section of the Character Class page at Regular-Expressions.info.

Hank Gay
None of the characters `(`, `)`, `{` and `}` have a special meaning inside a character class, so `[^\(\{\}\)]` can be written as `[^({})]`.
Bart Kiers
Thanks. I updated the example accordingly.
Hank Gay
+1  A: 
[^(){}\r\n]+\{0}[^(){}\r\n]+

will match any text except (, ), {, } and linebreaks, then match {0}, then the same as before. There needs to be at least one character before and after the {0}; if you don't want that, replace + with *.

You might also want to anchor the regex to beginning and end of your input string:

^[^(){}\r\n]+\{0}[^(){}\r\n]+$
Tim Pietzcker
+1  A: 

(Similar to Tim's answer)

Something like:

^[^{}()]*(\{0})[^{}()]*$

Tested at http://www.regular-expressions.info/javascriptexample.html

toolkit
+6  A: 

I hate to be the guy who doesn't answer the question, but really it's poor usability to ask your user to format input to work with String.Format. Provide them with two input requests, so they enter the part before the {0} and the part after the {0}. Then you'll want to just concatenate the strings instead of use String.Format- using String.Format on user-supplied text is just a bad idea.

Brian Schroth
good point Brian
toolkit
Absolutely! If you do that, you just need to check the input strings against `^[^(){})+$` (assuming these are the only characters that might break your application).
Tim Pietzcker
Drat. I meant `^[^(){}]+$`. Sorry.
Tim Pietzcker
Thanks to you all for the quick and detailed answers!!! Brian, you are right about the String.Format on user-supplied text! The thought of making the user type in a string for a String.Format troubles me, too. The problem is just that I can not be sure, if the user wants the value filled in only once or several times like in Text{0}Text{0}Text. :( I think in 99 % of all cases it will be something like 'Parameter={0}', then I could definitely use your solution! I will have to discuss with the customer! But at any rate thanks again to all! :)
Nikki
If the customer requires the variable part to be in the string in multiple places, maybe you could develop some sort of build-as-you-go interface, so they enter some text, click "add text", then click "add parameter", then change the text and click "add text" again, then click "add parameter" again..."add text" would concatenate the contents of their text box to the string being built, and "add parameter" would concatenate the parameter to it. This would allow any number of insertions of the parameter without requiring the user to format their input a special way.
Brian Schroth
Hmm good idea. I will check if he wants it to appear in multiple places and if so really do it this way! Thank you!I just have another question: How can I tell him in the string before and after the placeholder, that a '{' can be inserted in principle, but that he has to write '{{', i.e. he can only insert an even number of '{'s?
Nikki
The whole point of this solution is that you don't need to restrict the user's input in any arcane way, because you are no longer going to use String.Format. Instead, you will just concatenate strings the old fashioned way: String result = "foo" + "bar";
Brian Schroth
ah ok I see, you're right! stupid mistake of mine! :) thank you! :)
Nikki
+1  A: 

I think your question can be answered by the regexp:

^(((\{\{|\}\}|\\"|\\\\|[^\{\}\"\\])*(\{0\}))+(\{\{|\}\}|\\"|\\\\|[^\{\}\"\\])*$

Explanation:

The expression is built up as follows:

^(allowed chars {0})+(allowed chars)*$

one or more sequences of allowed chars followed by a {0} with optional allowed chars at the end.

allowed chars is built of the 4 sequences you mentioned (I assumed the \ escape is \\ instead of \.) plus all chars that do not contain the escapes chars:

(\{\{|\}\}|\\"|\\\\|[^\{\}\"\\])

combined they make up the regexp I started with.

rsp
That regex gives me a headache :(
Amarghosh
hence the explanation of how it is build :)
rsp