PHP Regex - accept all positive numbers except for 1 - php

Regexes and I have a relationship of love and hate. I need to match (accept) all numbers except for number 1 and 0. Seeing it as math and not string, number >= 2 should be matched. Also please consider this is part of a Zend route param (reqs) so I have to go with regex unless I want to extend Route class, and etc. etc. :)
103 => 103
013 => 013
201 => 201
340 => 340
111 => 111
001 => no match
010 => 010
100 => 100
1 => no match
000 => no match
00 => no match
0 => no match
I've tried some variations of [^1][|\d+] (trying to nail one digit at a time :D) but so far I've failed horribly :(
Nailed it!!
The regex I was looking for appears to be the following
^([2-9]|[2-9]\d|[1-9]\d{1,})$

Just use negative lookahead to exclude patterns with all zeroes that optionally end in an one:
/^(?!0*1?$)\d+$/
If you read it without the parens, this regex matches anything that consists of one or more decimal digits. The parens contain an assertion that causes the regex to match only if the pattern 0*1?$ cannot be matched beginning at the start of the input, so this removes the scenario of all zeroes and one with any number of prepended zeroes.

Use negation on the result for matching all zeroes and ones
if(!preg_match("^[01]+$",$string)) {...}

Your thinking of it the wrong way.
^[01]+$
will match all that onyl contain 0 or 1.
If that matches reject it, if it doesnt match check its a valid number and you should have a match

//if the numbers only include 0 or 1 reurn false;else will return the numbers
function match_number($number){
if(preg_match("/^[01]*$/", $number) > 0){
return false;
} else {
return $number;
}
}

The following regex will match any number (not digits, but number as a whole) >= 2
^([2-9]|[2-9]\d|[1-9]\d{1,})$
Thanks for all the valuable help in the answers, some were really helpful and helped me reach the desired result.

Related

Use regex to verify an ISBN number

I need a regex to verify ISBN number entered by user.
ISBN must be a string contains only:
[10 or 13 digits] and hyphens
I tried ^[\d*\-]{10}|[\d*\-]{13}$ but it doesn't work.
My regex only matches: 978-1-5661, 1-56619-90, 1257561035
It should returns the results below:
"978-1-56619-909-4 2" => false
"978-1-56619-909-4" => true
"1-56619-909-3 " => false
"1-56619-909-3" => true
"isbn446877428ydh" => false
"55 65465 4513574" => false
"1257561035" => true
"1248752418865" => true
I really appreciate any help.
You can use this regex with a positive lookahead:
^(?=(?:\D*\d){10}(?:(?:\D*\d){3})?$)[\d-]+$
RegEx Demo
(?=(?:\D*\d){10}(?:(?:\D*\d){3})?$) is a positive lookahead that ensures we have 10 or 13 digits in the input.
As mentioned at the accepted answer, not all 10 or 13 digit numbers are valid ISBN.
An ISBN consists of five groups of numbers that make out 13 digits. In 2007 the standard moved from 10 digits. The five groups can accept various lengths of numbers, which makes ISBN challenging to validate.
Ref. https://en.wikipedia.org/wiki/International_Standard_Book_Number
One solution is this:
^(?:ISBN(?:-13)?:?\ )?(?=[0-9]{13}$|(?=(?:[0-9]+[-\ ]){4})[-\ 0-9]{17}$)97[89][-\ ]?[0-9]{1,5}[-\ ]?[0-9]+[-\ ]?[0-9]+[-\ ]?[0-9]$
Source: O'Reilly Regular Expressions Cookbook, 2nd edition
You may find many possible regexp for ISBN validation here: https://regexlib.com/Search.aspx?k=ISBN

How to match those numbers?

I have an array of numbers, for example:
10001234
10002345
Now I have a number, which should be matched against all of those numbers inside the array. The number could either be 10001234 (which would be easy to match), but it could also be 100001234 (4 zeros instead of 3) or 101234 (one zero instead of 3) for example. Any combination could be possible. The only fixed part is the 1234 at the end.
I cant get the last 4 chars, because it can also be 3 or 5 or 6 ..., like 1000123456.
Whats a good way to match that? Maybe its easy and I dont see the wood for the trees :D.
Thanks!
if always the first number is one you can use this
$Num=1000436346;
echo(int)ltrim($Num."","1");
output:
436346
$number % 10000
Will return the remainder of dividing a number by 10000. Meaning, the last four digits.
The question doesn't make the criteria for the match very clear. However, I'll give it a go.
First, my assumptions:
The number always starts with a 1 followed by an unknown number of 0s.
After that, we have a sequence of digits which could be anything (but presumably not starting with zero?), which you want to extract from the string?
Given the above, we can formulate an expression fairly easily:
$input='10002345';
if(preg_match('/10+(\d+)/',$input,$matches)) {
$output = $matches[1];
}
$output now contains the second part of the number -- ie 2345.
If you need to match more than just a leading 1, you can replace that in the expression with \d to match any digit. And add a plus sign after it to allow more than one digit here (although we're still relying on there being at least one zero between the first part of the number and the second).
$input='10002345';
if(preg_match('/\d+0+(\d+)/',$input,$matches)) {
$output = $matches[1];
}

My regex for testing phone issue

I want to validate these phone number formats:
517123123
+48517123123
+48 517 123 123
(48)517123123
(48)517 123 123
517-123-123
48 517-123-123
48/517-123-123
48 517 123 123
I wrote this regex:
(\+?)+(((\(([0-9]+){2,2}\)))|(([0-9]+){2,2})?)+(\/?)+(\s?)+(([0-9]+){9,9}|([0-9]+){3,3}(\s|-){1,1}([0-9]+){3,3}(\s|-){1,1}([0-9]+){3,3})
The problem is that it's makes big numbers like 8978978979878978967 valid. Where is my mistake?
Looking at just the end of the regex, I see something that you seem to be doing in multiple places;
([0-9]+){3,3}
The + says at least one repeat of [0-9], which makes 1111111111111 a perfectly valid match. You then limit it to exactly 3 of those matches, which can still be a very long number.
If you want exactly 3 digits, remove the +.
may be you lost anchors.... however, use my regex ^(\+?(\(\d{2}\)|(\d{2})|(\d{2}[/ ])))?((\d{3} \d{3} \d{3})|(\d{3}-\d{3}-\d{3})|(\d{9}))$
At the moment I can't see what your regex is doing, there is too much superfluous stuff in it.
You have too many groups
You want to repeat optional characters!?
e.g.:
(\+?)+, you don't need a group around and you don't want to repeat that, so \+? is what you want here.
(\s?)+, do you want to say "0 or more whitespaces"? Then \s* is what you need.
When you write e.g. {9,9}, then you can remove one digit, {9} is the same.
You are nesting quantifiers, thats the place where you allow too many characters. You have multiple places, where you do ([0-9]+){9,9}, that means 1 or more digits and repeat that 9 times.

problem with preg_match

I have to validate for a Laser Credit card. The card starts with either 6304, 6706, 6709, 6771 and is 16 or 19 digits in length. I have a preg_match and I am passing in the card number starting with 6706 and has 19 digits but it returns false.
// Laser (Laser) P: 6304, 6706, 6709, 6771 L: 16,19
} elseif (preg_match('/^(?:[6304|6706|6709|6771])\d{12,15}$/', $number)) {
$type = 'laser';
/^6(?:304|706|709|771)(?:\d{12}|\d{15})$/
Broken down:
/^ # start of line
6(?:304|706|709|771) # your 6xxx codes
(?:\d{12}|\d{15}) # 12 (16-4) or 15 (19-4) more numbers
$/ # end of pattern
To point out the mistakes you had:
(?:[6304|6706|6709|6771])
Remember that [] is a CLASS. That means to look for any of those characters within the brackets. If you're going for either/or, you need to use a group ().
Fixed it should look like: (?:6304|6706|6709|6771)
\d{12,15}
My understanding is you need fixed-length of numbers, not a variable one. Your quantifier is saying it can be 12, 13, ..., 15 more numbers. We only want 12 OR 15 more.

Bug in a PHP regex

I am trying to print "1" if there are at least two of the same figure in the match, else 0.
What is wrong in the regex?
if ( max ( array_map ('strlen', preg_split('/([0-9])[^0-9]*\1/', "1 2 3 1 4") ) ) == 1 )
echo 1;
else
echo 0;
echo preg_match('/(?<=^|[^0-9])([0-9)+)(?=[^0-9]).*(?<=[^0-9])\1(?=[^0-9]|$)/', "1 2 3 1 4");
Will match for any repeated number in the sequence, and echo 1 if there is something repeated, 0 if not.
(Original version just looked for something repeated after each other, this matches repeated anywhere in the string)
The [^0-9]* matches any number of NON-digit characters. So if there's another number, it will fail the match. Try replacing [^0-9]* with a simple .*, which will match digits or non-digits.
Try the following code. It should print 1 when there is a repeat number.
if(0 == strlen(preg_replace('/.*([0-9]).+\1.*/', '', '1 2 3 1 5 4')))
echo 1;
else echo 0;
The regex /.*([0-9]).+\1.*/ will match a number and another number (with .+ or anything in between them).
Hope this helps.
Try a lookahead assertion. I use "The Regex Coach" whenever I'm trying to figure something out. It doesn't give you hints or anything, but it does give immediate feedback.
Test string: "1 2 3 1 4 3"
Regex: ([0-9])(?=.*\1)
Basically the ()'s around the [0-9] store the result, and the lookahead (?= matches .* - any character and then \1 - what was matched first (so it looks for any number and then looks ahead to see if that number occurs again)
This will match both "1" and "3"
I'm not quite sure if php supports lookaheads, but that's my take.

Categories