I have this simple regex,
[\d]{1,5}
that matches any integer between 0 and 99999.
How would I modify it so that it didn't match 0, but matches 01 and 10, etc?
I know there is a way to do an OR like so...
[\d]{1,5}|[^0]{1}
(doesn't make much sense)
There a way to do an AND?
probably better off with something like:
0*[1-9]+[\d]{0,4}
If I'm right that translates to "zero or more zeros followed by at least one of the characters included in '1-9' and then up to 4 trailing decimal characters"
Mike
I think the simplest way would be:
[1-9]\d{0,4}
throw that between a ^$ if it makes sense in your case, and if so, add a 0* to the beginning:
^0*[1-9]\d{0,4}$
My vote is to keep the regex simple and do that as a separate compare outside the regex. If the regex passes, convert it to an int and make sure the converted value is > 0.
But I know that sometimes one regex in a config file or validation property on a control is all you get.
How about an OR between single digit numbers you will accept and multiple-digit numbers:
^[1-9]$|^\d{2,5}$
I think a negative lookahead would work. Try this:
#!/bin/perl -w
while (<>)
{
chomp;
print "OK: $_\n" if m/^(?!0+$)\d{1,6}$/;
}
Example trace:
0
00
000
0000
00000
000000
0000001
000001
OK: 000001
101
OK: 101
01
OK: 01
00001
OK: 00001
1000
OK: 1000
101
OK: 101
By using look-aheads you can achieve the effect of AND.
^(?=regex1)(?=regex2)(?=regex3).*
Though there is a bug in Internet Explorer, that sometimes doesn't treat (?= ) as zero-width.
http://blog.stevenlevithan.com/archives/regex-lookahead-bug
In your case:
^(?=\d{1,5}$)(?=.*?[1-9]).*
It looks like you are searching for 2 different conditions. Why not break it out to 2 expressions? It might be simpler and more readable.
var str = user_string;
if ('0' != str && str.matches(/^\d{1,5}$/) {
// code for match
}
or the following if a string of 0's is not valid as well
var str = user_string;
if (!str.matches(/^0+$/) && str.matches(/^\d{1,5}$/) {
// code for match
}
Just because you can do it all in one regex doesn't mean that you should.
^([1-9][0-9]{0,4}|[0-9]{,1}[1-9][0-9]{,3}|[0-9]{,2}[1-9][0-9]{,2}|[0-9]{,3}[1-9][0-9]|[0-9]{,4}[1-9])$
Not pretty, but it should work. This is more of a brute force approach. There's a better way to do it via grouping as well, but I'm drawing a blank on the actual implementation at the moment.
Related
I have a specific requirement to check if all the characters in a string of 8 characters contains repeatition of character '0'
I was trying to use regular expression 0{8} to validate for all cases to get result as true -
but above regular expression will validate only *
0
00
000
0000
00000
000000
0000000
00000000 ->*
Can anyone suggest if i need to change something in my regular expression to validate all the above inputs ?
Appreciate your help.
To detect any number of repetitions of 0, simply use:
0+
This matches all your test cases, and of course would match more than 8, but if your input string is max 8 chars, it's OK.
You should use 0{1,8} to catch all cases you've provided.
{8} requires exactly 8 characters. Use a range:
0{1,8}
This should be easy with the following.
a = '000000000'
b = '000001000'
a.strip('0') # returns ''
b.strip('0') # returns '1'
For C++
replace( s.begin(), s.end(), '0', '');
i have a unique challenge.
i want to create a google analytics filter for a custom variable that only returns a value if the given string is smaller or equal than '001700'. yeah, i know that a string can't be smaller, still i need to find a way to make this work.
oh, and if you ask: no there is no way to convert that string to a number (according to my knowledge - via a google analytics filter - and that is what i have to work with in this case).
so basically, i have
000000
000001
000002
000003
...
...
999998
999999
and i need a regular expression that matches
001700
001699
001698
...
...
000001
000000
but does not match
001701
001702
...
...
999998
999999
sub question a) is it possible? (as i have learned, everything is possible with regExp if you are clever and/or masochistic enough)
sub question b) how to do it?
thx very much
You can do:
^00(1700|1[0-6][0-9]{2}|0[0-9]{3})$
See it
yes you can do
see this article
Eg:
alert('your numericle string'.replace(/\d+/g, function(match) {
return parseInt(match,10) <= 17000 ? '*' : match;
}));
JavaScript calls our function, passing
the match into our match argument.
Then, we return either the asterisk
(if the number matched is under 17000) or
the match itself (i.e. no match should
take place).
Can be done with RegEx:
/00(1([0-6][0-9]{2}|700)|0[0-9]{3})/
Explanation:
00 followed by
1 followed by 0 to 6 and any 2 numbers = 1000 - 1699
or
1700
or
0 followed by any 3 numbers = 0000 - 0999
What is the RegEx for value Range from 1- 365
Try this:
^(?:[1-9]\d?|[12]\d{2}|3[0-5]\d|36[0-5])$
The start anchor ^ and end anchor
$ are to match the whole input and
not just part of it.
(? ) is for grouping.
| is for alternation
[1-9]\d? matches 1 to 99
[12]\d{2} matches 100 to 299
3[0-5]\d matches 300 to 359
36[0-5] matches 360 to 365
You would have to list the possible combinations 1-9, 10-99, 100-299, 300-359, 360-365:
^([1-9]\d?|[12]\d\d|3[0-5]\d|36[0-5])$
Not really a good fit for regex, but if you insist:
^(?:36[0-5]|3[0-5][0-9]|[12][0-9][0-9]|[1-9][0-9]|[1-9])$
This is not allowing leading zeroes. If you wish to allow those, let me know.
The expression above can be shortened a little to
^(?:36[0-5]|3[0-5]\d|[12]\d{2}|[1-9]\d?)$
but I find the first solution to be a bit more readable. YMMV.
A general solution for matching the numbers from 1 to XYZ
^(?!0)(?!\d{4}$)(?![X+1-9]\d{2}$)(?!X[Y+1-9]\d$)(?!XY[Z+1-9]$)\d+$
Notes:
If any of X, Y or Z are 9 that will make X+1 etc. be 10. If that happens the regex part that would require using the 10 should be left out.
This can be extended to numbers with more or less digits following the same principles.
It does not allow left-padding 0es.
Applied to your case:
^(?!0)(?!\d{4}$)(?![4-9]\d{2}$)(?!3[7-9]\d$)(?!36[6-9]$)\d+$
Lets explain:
(?!0\d*) - does not start with 0
(?!\d{4}$) - does not have 4 digits, i.e. between 1000 and infinity
(?![4-9]\d{2}$) - it's not between 400 and 999
(?!3[7-9]\d$) - it's not between 370 and 399
(?!36[6-9]$) - it's not between 366 and 369
Test it.
^36[0-5]|(3[0-5]|[12]?[0-9])[0-9]$
^3(6[0-5]|[0-5]\d)|[12]\d\d|[1-9]\d|[1-9]$
Or if numbers like 05 can not be in input:
^3(6[0-5]|[0-5]\d)|[12]?\d?\d$
P.S.: Anyway no need of regex here. Use ToInt(), <=, >=
It really depends on your regex engine since they may not all be PCRE-style. I usually work to the lowest common denominator unless I know it will be targeting a minimum engine.
To that end, I'd just use something like:
^[1-9]|[1-9][0-9]|[1-2][0-9]{2}|3[0-5][0-9]|36[0-5]$
This will take care of (in order):
1-9.
10-99.
100-299.
300-359.
360-365.
However, unless you're absolutely required to use just a regex, I wouldn't. It's like trying to kill a fly with a thermo-nuclear warhead.
Just use the much simpler ^[0-9]{1,3}$ then use whatever language features you have to convert it to an integer and check it's between 1 and 365 inclusive:
def isValidDayOtherThanLeapYear (s):
if not s.matches ("^[0-9]{1,3}$"):
return false
n = s.toInteger()
if n < 1 or n > 365:
return false
return true
Your code will be more readable that way and I tend to rethink the use of regular expressions the second they start looking like they may be hard to read six months down the track.
This worked for me...
^[1-3][0-6]?[0-5]?$
I have a need to search all numbers with 4 digits between 2000 and 3000.
It can be that letters are before and after.
I thought I can use [2000-3000]{4}, but doesnt work, why?
thank you.
How about
^2\d{3}|3000$
Or as Amarghosh & Bart K. & jleedev pointed out, to match multiple instances
\b(?:2[0-9]{3}|3000)\b
If you need to match a3000 or 3000a but not 13000, you would need lookahead and lookbefore like
(?<![0-9])(?:2[0-9]{3}|3000)(?![0-9])
Regular expressions are rarely suitable for checking ranges since for ranges like 27 through 9076 inclusive, they become incredibly ugly. It can be done but you're really better off just doing a regex to check for numerics, something like:
^[0-9]+$
which should work on just about every regex engine, and then check the range manually.
In toto:
def isBetween2kAnd3k(s):
if not s.match ("^[0-9]+$"):
return false
i = s.toInt()
if i < 2000 or i > 3000:
return false
return true
What your particular regex [2000-3000]{4} is checking for is exactly four occurrences of any of the following character: 2,0,0,0-3,0,0,0 - in other words, exactly four digits drawn from 0-3.
With letters before an after, you will need to modify the regex and check the correct substring, something like:
def isBetween2kAnd3kWithLetters(s):
if not s.match ("^[A-Za-z]*[0-9]{4}[A-Za-z]*$"):
return false
idx = s.locate ("[0-9]")
i = s.substring(idx,4).toInt()
if i < 2000 or i > 3000:
return false
return true
As an aside, a regex for checking the range 27 through 9076 inclusive would be something like this hideous monstrosity:
^2[7-9]|[3-9][9-9]|[1-9][0-9]{2}|[1-8][0-9]{3}|90[0-6][0-9]|907[0-6]$
I think that's substantially less readable than using ^[1-9][0-9]+$ then checking if it's between 27 and 9076 with an if statement?
Hum tricky one. The dash - only applies to the character immediately before and after so what your regex is actually matching is exactly 4 characters between 0 and 3 inclusive (ie, 0, 1, 2 and 3). eg, 3210, 1230, 3333, etc... Try the expression below.
(2[0-9]{3})|(3000)
Here's explanation why and ways to detect ranges: http://www.regular-expressions.info/numericranges.html
Correct regex will be \b(2\d{3}|3000)\b. That means: match character '2' then exactly three digits (this will match any from 2000 to 2999) or just match '3000'. There are some good tutorials on regular expressions:
http://gnosis.cx/publish/programming/regular_expressions.html
http://immike.net/blog/2007/04/06/the-absolute-bare-minimum-every-programmer-should-know-about-regular-expressions/
http://www.regular-expressions.info/
why don't you check for greater or less than? its simpler than a regex
num >= 2000 and num <=3000
I have a sequence of digits like below. I want to combine digits to group of 4. Can someone give a vim regex to do that?
Input : 1234 56 7890 1234
The output should be: 1234 5678 9012 34
Two pass:
s/ //g
s/\(.\{4\}\)/\1 /g
I would do this in two steps:
(1) remove the blanks right of digit groups
:s/\(\d\+\) /\1/g
(2) grouping:
:s/\(\d\{4}\)/\1 /g
In case of many lines record a macro
or do these steps for an marked area.
You can do it in one pass, but it looks awful:
:s/\(\d\) *\(\d\) *\(\d\) *\(\d\) */\1\2\3\4 /g
While this works, it's rather asinine. It's faster to do one of those nice two-pass solutions than to spend 2 minutes working out one Monsteregex™ that does it in one pass. Plus, the two-pass solutions are easier to understand.
:s/\(\d\)\s*\(\d\)\s*\(\d\)\s*\(\d\)\s*/\1\2\3\4 /g
works, but I prefers Autocracy's solution.