Regex to match string not ending with pattern - regex

I try to find a regex that matches the string only if the string does not end with at least three '0' or more. Intuitively, I tried:
.*[^0]{3,}$
But this does not match when there one or two zeroes at the end of the string.

If you have to do it without lookbehind assertions (i. e. in JavaScript):
^(?:.{0,2}|.*(?!000).{3})$
Otherwise, use hsz's answer.
Explanation:
^ # Start of string
(?: # Either match...
.{0,2} # a string of up to two characters
| # or
.* # any string
(?!000) # (unless followed by three zeroes)
.{3} # followed by three characters
) # End of alternation
$ # End of string

You can try using a negative look-behind, i.e.:
(?<!000)$
Tests:
Test Target String Matches
1 654153640 Yes
2 5646549800 Yes
3 848461158000 No
4 84681840000 No
5 35450008748 Yes
Please keep in mind that negative look-behinds aren't supported in every language, however.

What wrong with the no-look-behind, more general-purpose ^(.(?!.*0{3,}$))*$?
The general pattern is ^(.(?!.* + not-ending-with-pattern + $))*$. You don't have to reverse engineer the state machine like Tim's answer does; you just insert the pattern you don't want to match at the end.

This is one of those things that RegExes aren't that great at, because the string isn't very regular (whatever that means). The only way I could come up with was to give it every possibility.
.*[^0]..$|.*.[^0].$|.*..[^0]$
which simplifies to
.*([^0]|[^0].|[^0]..)$
That's fine if you only want strings not ending in three 0s, but strings not ending in ten 0s would be long. But thankfully, this string is a bit more regular than some of these sorts of combinations, and you can simplify it further.
.*[^0].{0,2}$

Related

Regular expression with "not character" not matches as expected

I am trying to satisfy next restrictions:
line has from 3 to 256 chars that are a-z, 0-9, dash - or dot .
this line cannot start or end with -
I want to get kind of next output:
aaa -> good
aaaa -> good
-aaa -> bad
aaa- -> bad
---a -> bad
A have some of regexes that don't give right answer:
1) ^[^-][a-z0-9\-.]{3,256}[^-]$ gives all test lines as bad;
2) ^[^-]+[a-z0-9\-.]{3,256}[^-]+$ treats first three lines as one matching string since [^-] matches new line I guess.
3) ^[^-]?[a-z0-9\-.]{3,256}[^-]?$ (? for one or zero matching dash) gives all test lines as good
Where is the truth? I'm sensing it's either close to mine or much more complicated.
P.S. I use python 3 re module.
This one is almost correct: ^[^-][a-z0-9\-.]{3,256}[^-]$
The [^-] at the start and end represent one character already, so you will need to change {3,256} into {1,254}
Also, you probably only want a-z, 0-9 and . at the start and end (not just anything except -), so the full regex becomes:
^[a-z0-9.][a-z0-9\-.]{1,254}[a-z0-9.]$
Use a lookahead to confirm that the line matches your basic requirement ((?=^[0-9a-z.-]{3,256}$)) and then apply further restrictions.:
^((?=^[0-9a-z.-]{3,256}$)[^-].*[^-])$
Regex101 link
You can use this:
^(?!-)[a-z0-9.-]{3,256}(?<!-)$
Where (?!-) is a negative lookahead assertion (not followed by a dash) and (?<!-) is a negative lookbehind (not preceded by a dash).
You don't want {3,256}... You want {1,254} because [^-] each also match 1 character at the beginning and end of your string, so you have to subtract them from the total amount of characters that you want.
^[a-z0-9.][a-z0-9.-]{1,254}[^a-z0-9.]$
Or, if you want to keep your values you can also use lookahead/behinds:
^(?=[a-z0-9.])[a-z0-9.-]{3,256}(?<=[a-z0-9.])$

Regular Expression - 4 digits in a row, but can't be all zeros

I am looking for a solution that can exclusively be done with a regular expression. I know this would be easy with variables, substrings, etc.
And I am looking for PCRE style regex syntax even though I mention vim.
I need to identify strings with 4 numeric digits, and they can't be all 0's. So the following strings would be a match:
0001
1000
1234
0101
And this would not:
0000
This is a substring that will occur at a set location within a large string, if that matters; I don't think it should. For example
xxxxxxxxxxxx0001xxxxx
xxxxxxxxxxxx1000xxxxx
xxxxxxxxxxxx1234xxxxx
xxxxxxxxxxxx0101xxxxx
xxxxxxxxxxxx0101xxxxx
xxxxxxxxxxxx0000xxxxx
(?<!\d)(?!0000)\d{4}(?!\d)
or, more kindly/maintainably/sanely:
m{
(?<! \d ) # current point cannot follow a digit
(?! 0000 ) # current point must not precede "0000"
\d{4} # match four digits at this point, provided...
(?! \d ) # that they are not then followed by another digit
}x
Since I complained that the some of the answers here weren't regular expressions, I thought I'd best give you a regex answer. This is primitive, there's probably a better way, but it does work:
([1-9][0-9][0-9][0-9]|[0-9][1-9][0-9][0-9]|[0-9][0-9][1-9][0-9]|[0-9][0-9][0-9][1-9])
This checks for something which contains 0-9 in each location, except one which must lie in 1-9, preventing 0000 from matching. You can probably write this simpler using \d instead of [0-9] if your regex parser supports that metacharacter.
Just match for 4 digits (\d{4} should do it) and then verify that your match is not equal to '0000'.
Since PCRE supports lookarounds, \d{4}(?<!0000) will find any instance of four consecutive non-zero characters. See it in action here.
If you must make sure the match only occurs in the correct position of the string, you can use ^.{X}\d{4}(?<!0000).{Y}$ instead, where X and Y are the number of preceding and following characters, respectively (12 and 5 in your example.)
Test for a sequence of 3 digits (0-9), then a 4th with only (1-9)
/\d{3}[1-9]/

regular expression for matching

It is for a normal register name, could be 1-n characters with a-zA-Z and -, like
larry-cai, larrycai, larry-c-cai, l,
but - can't be the first and end character, like
-larry, larry-
my thinking is like
^[a-zA-Z]+[a-zA-Z-]*[a-zA-Z]+$
but the length should be 2 if my regex
should be simple, but don't how to do it
Will be nice if you can write it and pass http://tools.netshiftmedia.com/regexlibrary/
You didn't specify which regex engine you're using. One way would be (if your engine supports lookaround):
^(?!-)[A-Za-z-]+(?<!-)$
Explanation:
^ # Start of string
(?!-) # Assert that the first character isn't a dash
[A-Za-z-]+ # Match one or more "allowed" characters
(?<!-) # Assert that the previous character isn't a dash...
$ # ...at the end of the string.
If lookbehind is not available (for example in JavaScript):
^(?!-)[A-Za-z-]*[A-Za-z]$
Explanation:
^ # Start of string
(?!-) # Assert that the first character isn't a dash
[A-Za-z-]* # Match zero or more "allowed" characters
[A-Za-z] # Match exactly one "allowed" character except dash
$ # End of string
This should do it:
^[a-zA-Z]+(-[a-zA-Z]+)*$
With this there need to be one or more alphabetic characters at the begin (^[a-zA-Z]+). And if there is a - following, it needs to be followed by at least one alphabetic character (-[a-zA-Z]+). That pattern can be repeated arbitrary times until the end of the string is reached.
A simple answer would be:
^(([a-zA-Z])|([a-zA-Z][a-zA-Z-]*[a-zA-Z]))$
This matches either a string with length 1 and characters a-zA-Z or it matches an improved version of your original expression which is fine for strings with length greater than 1.
Credit for the improvement goes to Tim and ridgerunner (see comments).
Try this:
^[a-zA-Z]+([-]*[a-zA-Z])*$
Not sure which lazy group takes precedence..
^[a-zA-Z][a-zA-Z-]*?[a-zA-Z]?$
maybe this?
^[^-]\S*[^-]$|^[^-]{1}$

Regex for password that requires one numeric or one non-alphanumeric character

I'm looking for a rather specific regex and I almost have it but not quite.
I want a regex that will require at least 5 charactors, where at least one of those characters is either a numeric value or a nonalphanumeric character.
This is what I have so far:
^(?=.*[\d]|[!##$%\^*()_\-+=\[{\]};:|\./])(?=.*[a-z]).{5,20}$
So the problem is the "or" part. It will allow non-alphanumeric values, but still requires at least one numeric value. You can see that I have the or operator "|" between my require numerics and the non-alphanumeric, but that doesn't seem to work.
Any suggestions would be great.
Try:
^(?=.*(\d|\W)).{5,20}$
A short explanation:
^ # match the beginning of the input
(?= # start positive look ahead
.* # match any character except line breaks and repeat it zero or more times
( # start capture group 1
\d # match a digit: [0-9]
| # OR
\W # match a non-word character: [^\w]
) # end capture group 1
) # end positive look ahead
.{5,20} # match any character except line breaks and repeat it between 5 and 20 times
$ # match the end of the input
Perhaps this may work for you:
^.*[\d\W]+.*$
And use some code like this to check string size:
if(str.len >= 5 && str.len =< 20 && regex.ismatch(str, "^.*[\d\W]+.*$")) { ... }
Is it really necessary to stuff everything in a giant regex? Just use program logic (5 ≤ length(s) ≤ 20) ∧ (/[[:digit:]]/ ∨ /[^[:alpha:]]/). Far more readable syntactically and semantically, I think.
Pretty simple solution, once S.Mark got me on the right track, just needed to merge my numeric and non-alphanumeric pieces as one.
Here's the final regex for anyone that's interested:
^(?=.*[\d!##$%\^*()_\-+=\[{\]};:|\./])(?=.*[a-z]).{5,20}$
This will allow any password between 5 and 20 characters and requires at least one letter and one numeric and/or one non-alphanumeric character.
How about like this?
^.*?[\d!##$%\^*()_\-+=\[{\]};:|\./].*$
For the length 5,20 Please use normal strlen function

Regular Expression to match set of arbitrary codes

I am looking for some help on creating a regular expression that would work with a unique input in our system. We already have some logic in our keypress event that will only allow digits, and will allow the letter A and the letter M. Now I need to come up with a RegEx that can match the input during the onblur event to ensure the format is correct.
I have some examples below of what would be valid. The letter A represents an age, so it is always followed by up to 3 digits. The letter M can only occur at the end of the string.
Valid Input
1-M
10-M
100-M
5-7
5-20
5-100
10-20
10-100
A5-7
A10-7
A100-7
A10-20
A5-A7
A10-A20
A10-A100
A100-A102
Invalid Input
a-a
a45
4
This matches all of the samples.
/A?\d{1,3}-A?\d{0,3}M?/
Not sure if 10-A10M should or shouldn't be legal or even if M can appear with numbers. If it M is only there without numbers:
/A?\d{1,3}-(A?\d{1,3}|M)/
Use the brute force method if you have a small amount of well defined patterns so you don't get bad corner-case matches:
^(\d+-M|\d+-\d+|A\d+-\d+|A\d+-A\d+)$
Here are the individual regexes broken out:
\d+-M <- matches anything like '1-M'
\d+-\d+ <- 5-7
A\d+-\d+ <- A5-7
A\d+-A\d+ <- A10-A20
/^[A]?[0-9]{1,3}-[A]?[0-9]{1,3}[M]?$/
Matches anything of the form:
A(optional)[1-3 numbers]-A(optional)[1-3 numbers]M(optional)
^A?\d+-(?:A?\d+|M)$
An optional A followed by one or more digits, a dash, and either another optional A and some digits or an M. The '(?: ... )' notation is a Perl 'non-capturing' set of parentheses around the alternatives; it means there will be no '$1' after the regex matches. Clearly, if you wanted to capture the various bits and pieces, you could - and would - do so, and the non-capturing clause might not be relevant any more.
(You could replace the '+' with '{1,3}' as JasonV did to limit the numbers to 3 digits.)
^A?\d{1,3}-(M|A?\d{1,3})$
^ -- the match must be done from the beginning
A? -- "A" is optional
\d{1,3} -- between one and 3 digits; [0-9]{1,3} also work
- -- A "-" character
(...|...) -- Either one of the two expressions
(M|...) -- Either "M" or...
(...|A?\d{1,3}) -- "A" followed by at least one and at most three digits
$ -- the match should be done to the end
Some consequences of changing the format. If you do not put "^" at the beginning, the match may ignore an invalid beginning. For example, "MAAMA0-M" would be matched at "A0-M".
If, likewise, you leave $ out, the match may ignore an invalid trail. For example, "A0-MMMMAAMAM" would match "A0-M".
Using \d is usually preferred, as is \w for alphanumerics, \s for spaces, \D for non-digit, \W for non-alphanumeric or \S for non-space. But you must be careful that \d is not being treated as an escape sequence. You might need to write it \\d instead.
{x,y} means the last match must occur between x and y times.
? means the last match must occur once or not at all.
When using (), it is treated as one match. (ABC)? will match ABC or nothing at all.
I’d use this regular expression:
^(?:[1-9]\d{0,2}-(?:M|[1-9]\d{0,2})|A[1-9]\d{0,2}-A?[1-9]\d{0,2})$
This matches either:
<number>-M or <number>-<number>
A<number>-<number> or A<number>-A<number>
Additionally <number> must not begin with a 0.