Preg_match cuts last zeros from some numbers - php

I think it only happens when I write a regex. I have a simple regex to validate a set of pagination numbers, that later will be submitted to database, like 5, 10, 25, 50, 100, 250 example:
/all|5|10|25|50|100|250/
When I perform a test, my regex above cuts 0 only from numbers 50, 100 and 250 but not from 10!!?
Online example:
http://viper-7.com/IbKFKw
What am I doing wrong here? What am I really missing this time?

This is because in the string 50, the regex first matches 5, which is valid. In the string 250, the regex first matches 25, which is valid and ends here.
You might try adding anchors:
/^(?:all|5|10|25|50|100|250)$/
This forces the regex to match the whole string, and hence, return the correct match you are looking for.

The alternatives are tried from left to right, so matching 5 takes precedence over 50. But there's no 1 to cut off the 0 from 10. You can simply reorder them:
/all|250|100|50|25|10|5/
Alternatively, add the 0 optionally to the relevant alternatives (and since ? is greedy, the 0 will be matched if present):
/all|50?|100?|250?/
or
/all|(?:5|10|25)0?/
If this is not for matching but for validation (i.e. checking against the entire string), then go with Jerry's suggestion and use anchors to make sure that there are no undesired characters around your number:
/^(?:all|5|10|25|50|100|250)$/
(Of course inside (?:...) you could also use any of my above patterns, but now precedence is irrelevant because incomplete matches are disallowed.)

Related

Combine two regular expressions for php

I have these two regular expression
^(((98)|(\+98)|(0098)|0)(9){1}[0-9]{9})+$
^(9){1}[0-9]{9}+$
How can I combine these phrases together?
valid phone :
just start with : 0098 , +98 , 98 , 09 and 9
sample :
00989151855454
+989151855454
989151855454
09151855454
9151855454
You haven't provided what passes and what doesn't, but I think this will work if I understand correctly...
/^\+?0{0,2}98?/
Live demo
^ Matches the start of the string
\+? Matches 0 or 1 plus symbols (the backslash is to escape)
0{0,2} Matches between 0 and 2 (0, 1, and 2) of the 0 character
9 Matches a literal 9
8? Matches 0 or 1 of the literal 8 characters
Looking at your second regex, it looks like you want to make the first part ((98)|(\+98)|(0098)|0) in your first regex optional. Just make it optional by putting ? after it and it will allow the numbers allowed by second regex. Change this,
^(((98)|(\+98)|(0098)|0)(9){1}[0-9]{9})+$
to,
^(?:98|\+98|0098|0)?9[0-9]{9}$
^ this makes the non-grouping pattern optional which contains various alternations you want to allow.
I've made few more corrections in the regex. Use of {1} is redundant as that's the default behavior of a character, with or without it. and you don't need to unnecessarily group regex unless you need the groups. And I've removed the outer most parenthesis and + after it as that is not needed.
Demo
This regex
^(?:98|\+98|0098|0)?9[0-9]{9}$
matches
00989151855454
+989151855454
989151855454
09151855454
9151855454
Demo: https://regex101.com/r/VFc4pK/1/
However note that you are requiring to have a 9 as first digit after the country code or 0.

preg_match_all for Unknown Sets of 3 Integers

I am using preg_match_all, but I have a problem I am not sure can be solved using this method. The following line is part of what I am retrieving:
XXC033-101-143-147-175-142115-
The sets of numbers (033-101-143, etc) are what I want to refer to. However, the number of sets (always containing three integers) is unknown and can range anywhere from 1 to 10. If I knew there would always only be 2 sets, I would have the following:
if (preg_match_all('#([A-Z]{2}C)([0-9]{3})-([0-9]{3})-([0-9]{6})#', $wwalist, $matches))
...rest of code...
Is there anyway to do this when I have no way of knowing the number of possible sets of 3 integers. They will always be between the #([A-Z]{2}C) and -([0-9]{6}).
Any help would be greatly appreciated! Thanks!
Use
'#([A-Z]{2}C)([0-9]{3}-){1,10}([0-9]{6})#'
{1,10} specifies that the preceding subpattern enclosed in brackets [0-9]{3}- will repeat 1-10 times.
In addition:
If it can repeat 0 or more times for an indefinite maximum number, use *.
If it can repeat 1 or more times for an indefinite maximum number, use +.
Targeting only the 3-digit substrings, individually/optionally capture the groups like this:
Pattern: (Demo)
/[A-Z]{2}C\K(\d{3}-)(\d{3}-)?(\d{3}-)?(\d{3}-)?(\d{3}-)?(\d{3}-)?(\d{3}-)?(\d{3}-)?(\d{3}-)?(\d{3}-)?/

Regex for exact number / sting match in between

I want to make a regex where I can find the exact number in between a string.
eg. finding the number 2 in 3, 5, 25, 22,2, 15
What I have is /*,2,*/.
But with this regex it matches 22,25 or just anything with a 2 in it. I want it where only match where the number 2 itself is between the commas or without the commas standing alone.
*Update
Both the number(needle) i look for and string(haystack) where i seek it can vary.
Eg if the number i seek is always 2
I want to find them in 2,3,44,23,22,1 or 3,4,22,5,2 or 2 and i should be able to find one match for each of the group of numbers.
You should probably use boundaries (\b) so a leading/trailing comma isn't required.
/\b2\b/
You should do this instead:
,(\d), #for any single digit
,(2), #for 2 in particular
Demo: http://regex101.com/r/vP6jI1

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

Rotation in PHP's regex

How can you match the following words by PHP, either by regex/globbing/...?
Examples
INNO, heppeh, isi, pekkep, dadad, mum
My attempt would be to make a regex which has 3 parts:
1st match match [a-zA-Z]*
[a-zA-Z]?
rotation of the 1st match // Problem here!
The part 3 is the problem, since I do not know how to rotate the match.
This suggests me that regex is not the best solution here, since it is too very inefficient for long words.
I think regex are a bad solution. I'd do something with the condition like: ($word == strrev($word)).
Regexs are not suitable for finding palindromes of an arbitrary length.
However, if you are trying to find all of the palindromes in a large set of text, you could use regex to find a list of things that might be palindromes, and then filter that list to find the words that actually are palindromes.
For example, you can use a regex to find all words such that the first X characters are the reverse of the last X characters (from some small fixed value of X, like 2 or 3), and then run a secondary filter against all the matches to see if the whole word is in fact a palindrome.
In PHP once you get the string you want to check (by regex or split or whatever) you can just:
if ($string == strrev($string)) // it's a palindrome!
i think this regexp can work
$re = '~([a-z])(.?|(?R))\1~';

Categories