Regex for PHP - similar to IP pattern? - php

I need a regular expression which consist of: 1-3 digits and optional dot. It is something like IP pattern. I want my regex to allow the following:
192
192.
192.168
192.168.
and NOT the following:
192.1688
This is what I have so far:
preg_match('/^((\d{1,3})(\.?))+$/', $string);
But it still allows me to have more than 3 digits. Any suggestions how to fix the regex?

If you plan to match any number of 1-3 digit sequences separated with a dot (which is optional at the end), you can use
^\d{1,3}(?:\.\d{1,3})*\.?$
See demo
If you need the numbers to be in the range between 0 and 255 as in IP address, use
^(?:25[0-5]|2[0-4][0-9]|[01]?[1-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[1-9][0-9]?))*\.?$
See another demo.
To limit to only 2 groups of numbers, use a ? quantifier with the second non-capturing group:
^(?:25[0-5]|2[0-4][0-9]|[01]?[1-9][0-9]?)(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[1-9][0-9]?))?\.?$
^
See the 3rd demo

Related

PHP Regex for validation certain number format

I need a regular expression which validates any one of the below formats:
+10%
-123
+5.5
+50
99
99.99
-20%
25% (this should not be validated)
(% without any + or - should not be validated)
I tried to use preg_match('/^[+-]?(\d+\.)?(\d+)[%]?$/', $value) but this also validates 25%.
Can anyone share regex which validates the above format?
You may be able to do this using conditional sub-pattern in PCRE that avoids repeating whole number matching pattern again in alternation:
^([+-])?\d+(?:\.\d+)?(?(1)%)?$
RegEx Demo
RegEx Details:
^: Start
([+-])?: Match + or - in optional group #1
\d+: Match 1+ digits
(?:\.\d+)?: Match dot followed by 1+ digits in an optional non-capturing group
(?(1)%)?: Conditional subpattern. If group #1 is present then match % as optional match.
$: End
I might just keep it simple here and use an alternation:
^(?:[+-]?\d+(?:\.\d+)?|[+-]\d+(?:\.\d+)?%)$
Demo
The tricky part of your requirement is that the leading sign is optional for a non percentage number, but mandatory for a percentage. The alternation makes it easy to separate out these two concerns.

Regex Preg_match for licence key 25 alphanumeric and 4 hyphens

I'm still trying to get to grips with regex patterns and just after a little double-checking if someone wouldn't mind obliging!
I have a string which should either contain:
A 10 digit (numbers and letters) licence key, for example: 1234567890 OR
A 25 digit (numbers and letters) licence key, for example: ABCD1EFGH2IJKL3MNOP4QRST5 OR
A 29 digit licence number (25 numbers and letters, separated into 5 group by hyphens), for example: ABCD1-EFGH2-IJKL3-MNOP4-QRST51
I can match the first two fine, using ctype_alnum and strlen functions. However, for the last one I think I'll need to use regex and preg_match.
I had a go over at regex101.com and came up with the following:
preg_match('^([A-Za-z0-9]{5})+-+([A-Za-z0-9]{5})+-+([A-Za-z0-9]{5})+-([A-Za-z0-9]{5})+-+([A-Za-z0-9]{5})', $str);
Which seems to match what I'm looking for.
I want the string to only contain an exact match for a string beginning with the licence number, and contain nothing other than mixed upper/lower case letters and numbers in any order and hyphens between each group of 5 characters (so a total of 29 characters - I don't want any further matches). No white space, no other characters and nothing else before or after the 29 digit key.
Will the above work, without allowing any other combinations? Will it stop checking at 29 characters? I'm not sure if there is a simpler way to express this in regex?
Thanks for your time!
The main point is that you need to use both ^ (start of string) and $ (end of string) anchors. Also, when you use + after (...), you allow 1 or more repetitions of the whole subpattern inside the (...). So, you need to remove the +s and add the $ anchor. Also, you need regex delimiters for your regex to work in PHP preg_match. I prefer ~ so as not to escape /. Maybe it is not the case here, but this is a habit.
So, the regex can look like
'~^[A-Za-z0-9]{5}(?:-[A-Za-z0-9]{5}){4}$~'
See the regex demo
The (?:-[A-Za-z0-9]{5}){4} matches 4 occurrences of -[A-Za-z0-9]{5} subpattern. The (?:...) is a non-capturing group whose matched text does not get stored in any buffer (unlike the capturing group).
See the IDEONE demo:
$re = '~^[A-Za-z0-9]{5}(?:-[A-Za-z0-9]{5}){4}$~';
$str = "ABCD1-EFGH2-IJKL3-MNOP4-QRST5";
if (preg_match($re, $str, $matches)) {
echo "Matched!";
}
How about:
preg_match('/^([a-z0-9]{5})(?:-(?1)){4}$/i', $str);
Explanation:
/ : regex delimiter
^ : begining of string
( : begin group 1
[a-z0-9]{5} : exactly 5 alphanum.
) : end of group 1
(?: : begin NON capture group
- : a dash
(?1) : same as definition in group 1 (ie. [a-z0-9]{5})
){4} : this group must be repeated 4 times
$ : end of string
/i : regex delimiter with case insensitive modifier

Phone no contain this patteren AABBCC e.g 112233

I want to check if phone no contains this pattern AABBCC
Where A[0-9],B[0-9],C[0,9] They should be different e.g 112233,553322,887766
Let Us Suppose
I Have a phone no 03334112233
It will say yes pattern matched.
PHP Code but It Is For Exact String
$str = 'aabbaabbccaass'; //or whatever
if (preg_match('/(?!.*?aabbcc)^.*$/', $str))
echo "accepted\n";
else
echo "rejected\n";
Problem i don't know how to do if string is for numbers
Possible Duplicate
but it does not contain answer and exact detail.
Edited :
I want to match the last 6 characters of the string in this pattern AABBCC e.g 03329112233
To match number with AABBCC format, you can use this pattern:
(?:(\d)\1(?!\1)){2}(\d)\2
example of use:
if (preg_match('/(?:(\d)\1(?!\1)){2}(\d)\2/', $str)
echo "rejected\n";
else
echo "accepted\n";
But if you have other tests to do (for example that there is only digits), it can be more flexible to use it in this way:
if (preg_match('/(?!.*(?:(\d)\1(?!\1)){2}(\d)\2)^\d+$/', $str)
echo "accepted\n";
else
echo "rejected\n";
pattern details:
(?: # open a non capturing group that describes a repeated digit
(\d) # capture the first digit with group 1
\1 # a backreference to group 1 (the same digit thus)
(?!\1) # check with a negative lookahead that the same digit doesn't follow
){2} # repeat the group two times
(\d)\2 # same thing for digits 5 & 6 (the lookahead isn't needed here)
Note that the digit in the capture group change at each repetition of the non capturing group (because the negative lookahead forces it).
Notice: if you want to reject numbers that contains, for example, 111122 or 112222 or 111111, you only need to remove the negative lookahead.
if you want to reject numbers with the format 112211 or 448844, you must change the pattern like this: (\d)\1(?!\d{0,2}\1)(\d)\2(?!\2)(\d)\3
As I understand, you only want to match the last 6 characters of the string, if they are digits, and of 3 all different digit pairs. Would also use a lookahead and some pattern like this:
(?>((\d)\2)(?!.*\1)){3}$
\2 checks for an equivalent of 2nd capturing group, which is one digit (shorthand \d)
using a negative lookahead to check, if not followed by .* any amount of any characters, followed by equivalent of 1st capturing group (which contains 2 equal digits).
{3} 3 repitions at $ end of string.
Test on regex101.com, Regex FAQ
Your regex should be like this:
^((\d)\2){3}$
It is simpler and also works.
You can use capturing groups and backreferences like this:
if (preg_match('/(?!.*(.)\1(.)\2(.)\3)^.*$/', $str))
The (.) will match any single character and assign it to a group. The first instance is assigned to group 1, the second to group 2 and so on. Later in the pattern, the backreference \1 will match exactly what was previously captured in group the first group, \2 will match what was captured in the second group, etc.
You probably will also want to use \d to match any single digit (it's only necessary to use this outside of the lookahead) and a {n,m} quantifier to match between n and m digits. For example, the following will match any sequence of 7 to 10 digits that does not contain a subsequence like AABBCC:
if (preg_match('/(?!.*(.)\1(.)\2(.)\3)^\d{7,10}$/', $str))

Return numbers from a string

In PHP how can I determine if a zip code exists within a string, and if so, return the zip code. In this context, a zip code can be either a string of 5 numbers (ie "55543") or a string of 5 numbers connected to 4 more numbers with a hyphen (ie "74657-9993")..
Can anyone help me out with a Regex pattern I can use with preg_match or any other good ways of doing this?
I have preg_match_all("/\d{5}/", $str, $matches); so far, but that doesn't account for the possible second 4 digits or the hyphen.
5 number connected to 4 more numbers with a hyphen:
preg_match_all("/\b\d{5}(?:-\d{4})?\b/", $str, $matches);
(?:-\d{4,})? is an optional group, with a hyphen, and at least 4 digits after it.
Edit: Forgot to prevent longer than 5 digits for the first part (and 4 digits for the second part), using a word boundary.
EDIT2:
Okay, something else I just noticed is that if you have 12345-12345 but don't want to get any number form this, you would use:
preg_match_all("/\b\d{5}(?!-\d{1,3}\b|-\d{5})(?:-\d{4})?\b/", $str, $matches);
The negative lookahead prevents the match of -12345 (or more digits, or less than 4 digits) if present, but allow only 4 digits ahead.
regex101 demo
Your pattern is
\b\d{5}(?:-\d{4})?\b
See it here on Regexr.
An important part here are the word boundaries \b, they ensure that not a part of a number is matched.
\d{5} is matching 5 digits as you already had it
(?:-\d{4})? is the optional part (because of the ? after the the group). The ?: at the start of the group is just making the group non-capturing.
I have recently implemented this in javascript
/^(\s*|\d{5}([\-]\d{4})?)$/;
Just modify your regex to allow the optional prefix:
preg_match_all("/\d{5}(\-\d{4})?/", $str, $matches);

How can I match 4 repeating numbers using regex (PCRE)

I would like to detect whether a user-chosen pin contains 4 identical numbers e.g 1111 or 2222. I'm using preg_match in PHP.
How can I adapt this answer to do this?
You could use this regex:
/(\d)\1{3}/
This matches a single digit (\d), and then matches that same digit 3 times \1{3}.
count(array_unique(str_split($pin))) > 1
Adapting from the answer you link to:
\b(\d)\1{3}\b
Instead of using \1+ that would match any number of repetitions of the first digit, you substitute it with \1{3} that will only allow three repetitions of the first digit, thus giving you the desired four digits when matched.
Or if you prefer:
\b(\d)\1\1\1\b

Categories