Bug in a PHP regex - php

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.

Related

PHP Regex Regular Expressions preg_match() only allow digits with commas

I've asked and it was answered but now, after years, it doesn't work.
I've even tried online regex validators. Not sure what is going on.
Version: PHP 7.0.30 on 64Bit OS
The string should only allow digits with commas.
No commas in the beginning or end.
Spaces between commas is ok but I'd rather not allow it.
The following isn't passing
My regex is:
$DateInvoicedIDs = "1031,453,808,387,111,342,962,706,251,442,362,858,950,738,310,288,99,665,1023,30,894,112,132,148,347,895,382,94,766,683,276,1104,658,34,348,235,786,769,2";
$reg = '/[0-9\s]+(,[0-9\s]+)*[0-9]$/';
if ( preg_match($reg, $DateInvoicedIDs) ) {
echo = $DateInvoicedIDs;
} else { echo "false"; }
I'm using preg_match and getting false.
Any idea?
Test your string and pattern # https://regex101.com/r/3TVmOv/1
When that loads, you will see that there is no match highlighted.
Then add a digit to the end of your string and Whalla! This is because (,[0-9\s]+)* is matching the final 2 and [0-9]$ cannot be satisfied because another digit is required.
If I understand your logic/requirements, I think I'd use ~^\d+(?:\s*,\s*\d+)*$~
This improves the validation because it doesn't allow a mixture of digits and spaces between commas like: 2, 3 4 56, 72 I don't think you want spaces in your comma-separated numerical values.
Pattern Demo
Code: (Demo)
$DateInvoicedIDs = "1031,453,808,387,111,342,962,706,251,442,362,858,950,738,310,288,99,665,1023,30,894,112,132,148,347,895,382,94,766,683,276,1104,658,34,348,235,786,769,2";
$reg = '/^\d+(?:\s*,\s*\d+)*$/';
if (preg_match($reg, $DateInvoicedIDs)) {
echo $DateInvoicedIDs;
} else {
echo "false";
}
It is not matching because of the last [0-9] in your regex. The * in (,[0-9\s]+)* is a greedy match which means that it is consuming all commas followed by digits in your string. There is nothing left after to match against the last [0-9].
So you probably want to reduce your regex to '/[0-9\s]+(,[0-9\s]+)*$/.
The last part of your regex [0-9]$ is what's causing it to fail:
[0-9\s]+ is matching the first number only 1031,
(,[0-9\s]+)* is covering everything until ,2 because it's a single number right after a comma which is what it's looking for
Then [0-9]$ is trying to find one more number but it can't
If the last number is a double-digit number, i.e. ,25 instead of 2, then the that second part (,[0-9\s]+)* would be satisfied because it found at least one number and [0-9]$ would match the next number which is 5 (https://regex101.com/r/0XbHsw/1)
Adding ? for that last part would solve the problem: [0-9\s]+(,[0-9\s]+)*[0-9]?$

Comparison of a string with given pattern

I am taking an input from the user in form field. I wanna make sure that the given input should be in the pattern like "2012-xxx-111" i-e 1st four should be integers and there should be a "-" sign after that there should be two or three alphabets after that the "-" and at the end any integer value consisting of 3 numbers. Help me doing all this in php. Thanks
your help would be appreciated .
You can use a regex for that.
[0-9]{4}-[A-Za-z]{2,3}-[0-9]{3}
This will match any number between 0 and 9 four times, following by a -, followed by 2 or 3 letters from a to z, lowercase or uppercase, and finally another - and 3 more numbers.
http://regexr.com/3bo81
In PHP, you can use preg_match() to see if a string matches a given pattern.
Use preg_match with a regex
if (preg_match("/^[0-9]{4}-[A-Za-z]{2,3}-[0-9]{3}$/", "Search String Here")) {
echo "A match was found.";
} else {
echo "A match was not found.";
}

PHP Regex - accept all positive numbers except for 1

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.

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];
}

Regex to validate numbers 0-100 with up to two decimal places

So I know it would be easier to just use the php is_numeric function, but what i'm trying to do is create a regular expression, mostly for learning regex, to test test scores. The range can be 0-100, but can have 2 decimal places. This is what I have so far and its not working.
if (preg_match("^([0-9]){2,3})(.[0-9]{2})?$([0-9]{1})?$", $quiz1))
{
echo "match";
}
else {
$error = true;
}
If I'm thinking correctly the literal meaning:
start of string find characters 0-9, for two places.
optional end of string decimal and find characters 0-9, for two places.
optional end of string find characters 0-9, for 1 place.
Why not something like this?
/^(?:100|\d{1,2})(?:\.\d{1,2})?$/
^ - beginning of string
(?:100|\d{1,2}) - non-capturing group, 100 or 0-99
(?:.\d{1,2})? - optional non-capturing group (.# or .##)
$ - end of string
Results:
php > $tests = array(0, 5, 10, 50, 100, 99.5, 75.43, 75.436, 101);
php > foreach ($tests as $test) { print $test . " - " . preg_match("/^(?:100|\d{1,2})(?:\.\d{1,2})?$/", $test) . "\n"; }
0 - 1
5 - 1
10 - 1
50 - 1
100 - 1
99.5 - 1
75.43 - 1
75.436 - 0
101 - 0
75F43 - 0
Yours doesn't work even when I add the slashes and remove the extra ).
php > foreach ($tests as $test) { print $test . " - " .
preg_match("/^([0-9]{2,3})(.[0-9]{2})?$([0-9]{1})?$/", $test) . "\n"; }
0 - 0
5 - 0
10 - 1
50 - 1
100 - 1
99.5 - 0
75.43 - 1
75.436 - 0
101 - 1
75F43 - 1
Surround your expression with / characters
http://php.net/manual/en/regexp.reference.delimiters.php
gpojd's answer is correct. However, here's why your regex isn't working.
First of all, you want the first $ inside the ()'s. Because otherwise it will need to match the end of the string, and then later after that the end of the string again, which is of course impossible.
Second, the dot character needs to become \. because a dot by itself matches any character, but you want an actual dot. Lastly, you need delimiters, like someone else suggested. Here's what your regex matches:
first, two or three digits, mandatory.
Then, any character followed by two digits, optionally.
Then, the end of the string, mandatory.
Then, one digit, optionally.
Then, the end of the string again, mandatory.
Since you're a programmer, it can be hard to get used to the way of thinking with regular expressions; you're used to thinking in terms of if-else statements but regular expressions don't really work that way.
Again, the option above is good enough but if I were to write a regex for this I'd put:
/^100(.00)?|([1-9]?[0-9])(\.[0-9]{2})?$/
So, either 100 followed by an optional .00, or: first, an optional nonzero digit and then a mandatory digit (those make the numbers 0 to 99), then optionally a dot followed by two digits.

Categories