I'm trying to add some validation in ASP.NET using Regex. Essentially I need to ensure a text box includes both ***ThisString*** and ***ThatString*** including the asterisks.
I can get it to work with one, or one or the other, just not both being present at the same time and at any part of the string.l it's validating.
Thanks
As nanhydrin correctly pointed out, my solution will not work if there are multiple of one of the strings but not the other. If that case may occur, you can check for each string separately for readability's sake
First regular expression- (?:\*{3}ThisString\*{3})
Second regular expression- (?:\*{3}ThatString\*{3})
If matches are found in both cases, you're good to go!
Original Answer:-
This is the regular expression you want: (?:\*{3}(?:ThisString|ThatString)\*{3})
Note: Make sure to have global match on and be sure to escape the asterisks correctly.
If the above expression finds 2 (or more) matches, it means you're good to go.
Explanation:-
The entire thing is in a non capturing group, this is to ensure, everything within does get matched fully
There are 3 stars on each side of the strings, having 3 stars on one side but not the other will not result in a match
Both ThisString and ThatString are in a grouped alternative, this is to reduce clutter, you could totally jam every possible positional pattern but this is just better as position doesn't matter here. ***ThatString*** can come before ***ThisString*** or vice versa.
MAKE SURE to check the length of the matches found, the length must be 2 for your
described condition to be satisfied.
Here's the live demo
Using #Chase's answer I was able to come up with the following:
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
Regex thisString = new Regex("(?:\*{3}ThisString\*{3})");
Regex thatString = new Regex("(?:\*{3}ThatString\*{3})");
if (!thisString.IsMatch(value.ToString()) || !thatString.IsMatch(value.ToString()))
{
return new ValidationResult("***ThisString*** and ***ThatString*** are used to generate the email text. Please ensure the text above has both ***ThisString*** and ***ThatString*** somewhere within the text."); }
return ValidationResult.Success;
}
Now if either regex patterns don't match anywhere, it'll return an error.
Related
I have been using strapplyc in R to select different portions of a string that match one particular set of criteria. These have worked successfully until I found a portion of the string where the required portion could be defined one of two ways.
Here is an example of the string which is liberally sprinkled with \t:
\t\t\tsome words here\t\t\tDefect: some more words here Action: more words
I can write the strapply statement to capture the text between Defect: and the start of Action:
strapplyc(record[i], "Defect:(.*?)Action")
This works and selects the chosen text between Defect: and Action. In some cases there is no action section to the string and I've used the following code to capture these cases.
strapplyc(record[i], "Defect:(.*?)$")
What I have been trying to do is capture the text that either ends with Action, or with the end of the string (using $).
This is the bit that keeps failing. It returns nothing for either option. Here is my failing code:
strapplyc(record[i], "Defect:(.*?)Action|$")
Any idea where I'm going wrong, or a better solution would be much appreciated.
If you are up for a more efficient solution, you could drop the .*? matching and unroll your pattern like:
Defect:((?:[^A]+|A(?!ction))*)
This matches Defect: followed by any amount of characters that are not an A or are an A and not followed by ction. This avoids the expanding that is needed for the lazy dot matching. It will work for both ways, as it does stop matching when it hits Action or the end of your string.
As suggested by Wiktor, you can also use
Defect:([^A]*(?:A(?!ction)[^A]*)*)
Which is a little bit faster when there are many As in the string.
You might want to consider to use A(?!ction:) or A(?!ction\s*:), to avoid false early matches.
The alternation operator | is the regex operator with the lowest precedence. That means the regex Defect:(.*?)Action|$ is actually a combination of Defect:(.*?)Action and $ - since an empty string is a valid match for $, your regex returns the empty string.
To solve that, you should combine the regexes Defect:(.*?)Action and Defect:(.*?)$ with an OR:
Defect:(.*?)Action|Defect:(.*?)$
Or you can enclose Action|$ in a group as Sebastian Proske said in the comments:
Defect:(.*?)(?:Action|$)
I am trying to write a regular expression for ASP.NET MapPageRoute that matches a specific type of path.
I do not want to match anything with a file extension so I used this regex ^[^.]*$ which worked fine except it also picked up if the default document was requested. I do not want it to pick up the default document so I have been trying to change it to require at least one character. I tried adding .{1,} or .+ to the beginning of the working regex but it stopped working alltogether.
routes.MapPageRoute("content", "{*contentpath}", "~/Content.aspx", true, new RouteValueDictionary { }, new RouteValueDictionary { { "contentpath", #"^[^.]*$" } });
How can I change my regex to accomplish this?
Unfortunately my brain does not seem capable of learning regular expressions properly.
You want to change your * quantifier to +. * matches zero or more times, whereas + matches one or more. So, what you are asking for is this:
^[^.]+$
The regex is accomplishing this: "At the beginning of the string, match all characters that are not ., at least one time, up to the end of the string."
^[^.]+$
zero is to * as one is to +
Sample text =
legacycard.ashx?save=false&iNo=3&No=555
Sample pattern =
^legacycard.ashx(.*)No=(\d+)
Want to grab group #2 value of "555" (the value of "No=" in the sample text)
In Expresso, this works, but in ASP.NET UrlRewrite, it is not catching.
Am I missing something?
Thanks!
I would do something along these lines:
^legacycard.ashx\?(?:.+&)*No=(\d+)
The \? will escape the question mark that normally separates the URL and the parameters, then you make sure that it will capture every parameter key/value pair (anything that ends on &) before the parameter you actually care about. Using ?: lets you specify that the set of brackets is non capturing (I'm assuming you won't need any of the data, has the potential to slightly speeds up your regex) and leaves you just 555 captured. The added benefit of this approach is that it'll work regardless of parameter order.
Just use this regex:
^legacycard\.ashx\?save=(false|true)&iNo=(?<ino>\d+)&No=(?<no>\d+)
Then Regex Replace with
${no}
Looks fine to me, your regex should match the entire string
legacycard.ashx?save=false&iNo=3&No=555
not sure why you have groups, but groups should also return
?save=false&iNo=3&
and
555
For good measure you should know that the . in legacycard.ashx is also interpreted by regex and you would normally escape it, in this case it dosen't matter because a single dot matches everything, also a dot. :)
Try this
^legacycard.ashx(\?No=|.*?&No=)(\d+)
this should work.
Using ASP.NET syntax for the RegularExpressionValidator control, how do you specify restriction of two consecutive characters, say character 'x'?
You can provide a regex like the following:
(\\w)\\1+
(\\w) will match any word character, and \\1+ will match whatever character was matched with (\\w).
I do not have access to asp.net at the moment, but take this console app as an example:
Console.WriteLine(regex.IsMatch("hello") ? "Not valid" : "Valid"); // Hello contains to consecutive l:s, hence not valid
Console.WriteLine(regex.IsMatch("Bar") ? "Not valid" : "Valid"); // Bar does not contain any consecutive characters, so it's valid
Alexn is right, this is the way you match consecutive characters with a regex, i.e. (a)\1 matches aa.
However, I think this is a case of everything looking like a nail when you're holding a hammer. I would not use regex to validate this input. Rather, I suggest validating this in code (just looping through the string, comparing str[i] and str[i-1], checking for this condition).
This should work:
^((?<char>\w)(?!\k<char>))*$
It matches abc, but not abbc.
The key is to use so called "zero-width negative lookahead assertion" (syntax: (?! subexpression)).
Here we make sure that a group matched with (?<char>\w) is not followed by itself (expressed with (?!\k<char>)).
Note that \w can be replaced with any valid set of characters (\w does not match white-spaces characters).
You can also do it without named group (note that the referenced group has number 2):
^((\w)(?!\2))*$
And its important to start with ^ and end with $ to match the whole text.
If you want to only exclude text with consecutive x characters, you may use this
^((?<char>x)(?!\k<char>)|[^x\W])*$
or without backreferences
^(x(?!x)|[^x\W])*$
All syntax elements for .NET Framework Regular Expressions are explained here.
You can use a regex to validate what's wrong as well as what's right of course. The regex (.)\1 will match any two consecutive characters, so you can just reject any input that gives an IsValid result to that. If this is the only validation you need, I think this way is far easier than trying to come up with a regex to validate correct input instead.
I found the answer to this, but it's a bit of a gotcha so I wanted to share it here.
I have a regular expression that validates passwords. They should be 7 to 60 characters with at least one numeric and one alpha character. Pretty standard. I used positive lookaheads (the (?= operator) to implement it:
(?=^.{7,60}$)(?=.*[0-9].*)(?=.*[a-zA-Z].*)
I checked this expression in my unit tests using Regex.IsMatch(), and it worked fine. However, when I use it in a RegularExpressionValidator, it always fails. Why?
It's strange that I've never run into this before, but it turns out that the RegularExpressionValidator doesn't use Regex.IsMatch or JavaScript's Regex.test() -- it checks for a capturing match that exactly equals the full tested value. Here's the relevant JS code:
var rx = new RegExp(val.validationexpression);
var matches = rx.exec(value);
return (matches != null && value == matches[0]);
So if the expression is all lookaheads (which match positions, not the actual text), it will fail. This is clearer with the example of an expression that only partially matches, e.g. with \d{5}, the value "123456" would fail. It's not just that it adds "^$" around your expression and does an IsMatch. Your expression actually has to capture.
The fix in my case is this expression:
(?=^.{7,60}$)(?=.*[0-9].*).*[a-zA-Z].*
Have you tried
(?=^.{7,60}$)(?=.*[0-9].*)(?=.*[a-zA-Z].*).+
// ^^
? The regex should need something to consume.