Regular Expression for starting woth specfic number - php

How to write regular expression for following conditions:
Should have only numbers
Must be 8 digits long
Must start with 8 or 9 or 6
So for I can do only for first two conditions. I am not sure how to do the third conditions
My code is
if (!preg_match('/^[0-9]{8}$/', $number))

You're almost there. Simply remove the first number from the character class and validate it at the start of your pattern...
/^(8|9|6)\d{7}$/
FYI - \d is the escape sequence for digits. I suppose you could also use this
/^[896]\d{7}$/
as it means about the same thing when you're only watching for a single character at the start.

Related

How to construct a regex expression for username validation? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I'm working on constructing a PHP regex expression for a username validation that has the following constraints:
-must be 10-16 characters long, with a combo of alphabetic, numeric, and atleast one special character (*&^-_$)
-can't start with a numeric or special character
CORRECTION: the last SIX digits must be a month/date birthday (MMYYYY format). In order to further validate the username, the month/date must show the username is over 18 - if not, the username will not validate. Thank you in advance for any assistance! I've been stuck on this for a while.
Solution
You can do this with the following regex:
/(?=^.{10,16}$)(?=.+?[*&^_$-])[a-z].+?[01]\d{3}$/i
Here's a demo with some unit tests.
Explanation
/ delimiter
(?=^.{10,16}$) ensures there are 10-16 characters, start to finish
(?= starts a lookahead group
^ start of the string
.{10,16} ten to sixteen characters
$ end of the string
) ends the lookahead group
(?=.+?[*&^_$-]) ensures there is at least one special character in the set *&^_$-, and it's not first
(?= starts a lookahead group
.+? one or more characters, non-greedy
[*&^_$-] any character in the set *&^_$- (note the order; you must put - first or last, or escape it as \-)
) ends the lookahead group
[a-z] start with a letter
.+? match any characters in a non-greedy fashion, giving back as needed
[01]\d{3} match a 0 or 1 then 3 more digits
$ match the end of the string
/ closing delimiter
i make the match case-insensitive
Some Notes on Regex Construction
Note that there are multiple valid ways to do this. For pure efficiency, the solution above could be simplified somewhat to cut out a few steps for the processor.
But for readability, I like to go with something like the above. It's clear what each block, character set, or group does, which makes it readable and maintainable.
Something like /^[a-z](?=.*?[*&^_$-])[a-z0-9*&^_$-]{5,11}[01]\d{3}$ is hard to read and understand. What if you want to allow a 17 character username? You have to do a bunch of math to determine that you should change {5,11} to {5,12}. Or if you decide to allow the character #, you'd have to add it in two places (which, by the way, means that the regex already violates the DRY principle).
Bonus: Why Your Attempt Failed
You said in a comment that you tried this:
(?=^.{10,16}$)^[a-z][\d]*[_$^&*]?[a-z0-9]+
The first part, (?=^.{10,16}$), is fine. So is ^[a-z].
But [\d]* only matches zero or more digits; it wouldn't match a letter or special character. So, for example, a&a... would fail.
And [_$^&*]? only matches zero or one special characters. It would allow a username with no special characters to pass, but would fail one with 2 special characters.
[a-z0-9]+ only matches those characters, and you omit your last-four-characters-must-be-digits requirement.
You might find the explanation on regex101.com of your regex helpful. (Note: I have no affiliation with that site.)
You can use this regex :
^[a-zA-Z](?=.*[*&^_$-])[\w*&^$-]{5,11}[01]\d{3}$
Regex Breakup:
^ # Line start
[a-zA-Z] # # match an alhpabet
(?=.*[*&^_$-]) # lookahead to ensure there is at least one special char
[\w*&^$-]{5,11} # match 5 to 11 of allowed chars
[01]\d{3} # match digits 0/1 followed by 3 digits
$ # Line end
I used quantifier {5,11} because one char is matches at start and 4 are being matched in the end thus taking out 5 positions from desired {10,16} lengths.

PCRE(php) Is it possible to check if sequence of numbers contains only unique number for that sequence?

Assuming I have a set of numbers (from 1 to 22) divided by some trivial delimiters (comma, point, space, etc). I need to make sure that this set of numbers does not contain any repetition of the same number. Examples:
1,14,22,3 // good
1,12,12,3 // not good
Is it possible to do via regular expression?
I know it's easy to do using just php, but I really wander how to make it work with regex.
Yes, you could achieve this through regex via negative looahead.
^(?!.*\b(\d+)\b.*\b\1\b)\d+(?:,\d+)+$
(?!.*\b(\d+)\b.*\b\1\b) Negative lookahead at the start asserts that the there wouldn't be a repeated number present in the match. \b(\d+)\b.*\b\1\b matches the repeated number.
\d+ matches one or more digits.
(?:,\d+)+ One or more occurances of , , one or more digits.
$ Asserts that we are at the end .
DEMO
OR
Regex for the numbers separated by space, dot, comma as delimiters.
^(?!.*\b(\d+)\b.*\b\1\b)\d+(?:([.\s,])\d+)(?:\2\d+)*$
(?:([.\s,])\d+) capturing group inside this non-capturing group helps us to check for following delimiters are of the same type. ie, the above regex won't match the strings like 2,3 5.6
DEMO
You can use this regex:
^(?!.*?(\b\d+)\W+\1\b)\d+(\W+\d+)*$
Negative lookahead (?!.*?(\b\d+)\W+\1\b) avoids the match when 2 similar numbers appear one after another separated by 1 or more non-word characters.
RegEx Demo
Here is the solution that fit my current need:
^(?>(?!\2\b|\3\b)(1\d{1}|2[0-2]{1}|\d{1}+)[,.; ]+)(?>(?!\1\b|\3\b)(1\d{1}|2[0-2]{1}|\d{1}+)[,.; ]+)(?>(?!\1\b|\2\b)(1\d{1}|2[0-2]{1}|\d{1}+))$
It returns all the sequences with unique numbers divided by one or more separator and also limit the number itself from 1 to 22, allowing only 3 numbers in the sequence.
See working example
Yet, it's not perfect, but work fine! Thanks a lot to everyone who gave me a hand on this!

Regex to allow numbers and only one hyphen in the middle

I am trying to write a regular expression to allow numbers and only one hypen in the middle (cannot be at start or at the end)
say pattern: 02-04 , 02are acceptable but
pattern: -- or - or -02 or 04- or 02-04-06 are unacceptable
I tried something like this but this would allow - at the beginning and also allow multiple -
'/^[0-9 \-]+$/'
I am not that good with regex so a little explanation would be real helpful.
EDIT: Sorry to bug you again with this but I need the numbers to be of only 2 digits (123-346) should be considered invalid.
Try this one:
/^\d{1,2}(-\d{1,2})?$/
One or two digits, followed by, optionally, ( a hyphen followed by one or two digits)
Fairly easy:
^\d+(-\d+)?$
At least one (+) digit (\d), followed by an optional group containing a hyphen-minus (-), followed by at least one digit again.
For strings containing only that pattern the following should work
^(\d{2}-)?\d{2}$
A group of 2 digits followed by minus ending with a group of 2 digits without minus.

How can I use regex to solve this?

I have two strings that I need to pull data out of but can't seem to get it working. I wish I knew regular expression but unfortunately I don't. I have read some beginner tutorials but I can't seem to find an expression that will do what I need.
Out of this first string delimited by the equal character, I need to skip the first 6 characters and grab the following 9 characters. After the equal character, I need to grab the first 4 characters which is a day and year. Lastly for this string, I need the remaining numbers which is a date in YYYYmmdd.
636014034657089=130719889904
The second string seems a little more difficult because the spaces between the characters differ but always seem to be delimited by at minimum, a single space. Sometimes, there are as many as 15 or 20 spaces separating the blocks of data.
Here are two different samples that show the space difference.
!!92519 C 01 M600200BLNBRN D55420090205M1O
!!95815 A M511195BRNBRN D62520070906 ":%/]Q2#0*&
The data that I need out of these last two strings are:
The zip code following the 2 exclamation marks.
The single letter 'M' following that. It always appears to be in a 13 character block
The 3 numbers after the single letter
The next 3 numbers which are the person's height
The following next 3 are the person's weight
The next 3 are eye color
The next block of 3 which are the person's hair color
The last block that I need data from:
I need to get the single letter which in the example appears to be a 'D'.
Skip the next 3 numbers
The last and remaining 8 numbers which is a date in YYYYmmdd
If someone could help me resolve this, I'd be very grateful.
For the first string you can use this regular expression:
^[0-9]{6}([0-9]{9})=([0-9]{4})([0-9]{4})([0-9]{2})([0-9]{2})$
Explanation:
^ Start of string/line
[0-9]{6} Match the first 6 digits
([0-9]{9}) Capture the next 9 digits
= Match an equals sign
([0-9]{4}) Capture the "day and year" (what format is this in?)
([0-9]{4}) Capture the year
([0-9]{2}) Capture the month
([0-9]{2}) Capture the date
$ End of string/line
For the second:
^!!([0-9]{5}) +.*? +M([0-9]{3})([0-9]{3})([A-Z]{3})([A-Z]{3}) +([A-Z])[0-9]{3}([0-9]{4})([0-9]{2})([0-9]{2})
Rubular
It works in a similar way to the first. You may need to adjust it slightly if your data is not exactly in the format that the regular expression expects. You might want to replace the .*? with something more precise but I'm not sure what because you haven't described the format of the parts you are not interested in.

Regex help to match more than one letter

I am using the following regex to match an account number. When we originally put this regex together, the rule was that an account number would only ever begin with a single letter. That has since changed and I have an account number that has 3 letters at the beginning of the string.
I'd like to have a regex that will match a minimum of 1 letter and a maximum of 3 letters at the beginning of the string. The last issue is the length of the string. It can be as long as 9 characters and a minimum of 3.
Here is what I am currently using.
'/^([A-Za-z]{1})([0-9]{7})$/'
Is there a way to match all of this?
You want:
^[A-Za-z]([A-Za-z]{2}|[A-Za-z][0-9]|[0-9]{2})[0-9]{0,6}$
The initial [A-Za-z] ensures that it starts with a letter, the second bit ([A-Za-z]{2}|[A-Za-z][0-9]|[0-9]{2}) ensures that it's at least three characters long and consists of between one and three letters at the start, and the final bit [0-9]{0,6} allows you to go up to 9 characters in total.
Further explaining:
^ Start of string/line anchor.
[A-Za-z] First character must be alpha.
( [A-Za-z]{2} Second/third character are either alpha/alpha,
|[A-Za-z][0-9] alpha/digit,
|[0-9]{2} or digit/digit
) (also guarantees minimum length of three).
[0-9]{0,6} Then up to six digits (to give length of 3 thru 9).
$ End of string/line marker.
Try this:
'/^([A-Za-z]{1,3})([0-9]{0,6})$/'
That will give you from 1 to 3 letters and from 3 to 9 total characters.

Categories