Capture the latest in backreference - regex

I have this regex
(\b(\S+\s+){1,10})\1.*MY
and I want to group 1 to capture "The name" from
The name is is The name MY
I get "is" for now.
The name can be any random words of any length.
It need not be at the beginning.
It need on be only 2 or 3 words. It can be less than 10 words.
Only thing sure is that it will be the last set of repeating words.
Examples:
The name is Anthony is is The name is Anthony - "The name is Anthony".
India is my country All Indians are India is my country - "India is my country "
Times of India Alphabet Google is the company Alphabet Google canteen - "Alphabet Google"

You could try:
(\b\w+[\w\s]+\b)(?:.*?\b\1)
As demonstrated here
Explanation -
(\b\w+[\w\s]+\b) is the capture group 1 - which is the text that is repeated - separated by word boundaries.
(?:.*?\b\1) is a non-capturing group which tells the regex system to match the text in group 1, only if it is followed by zero-or-more characters, a word-boundary, and the repeated text.

Regex generally captures thelongest le|tmost match. There are no examples in your question where this would not actualny be the string you want, but that could just mean you have not found good examples to show us.
With that out of the way,
((\S+\s)+)(\S+\s){0,9}\1
would appear to match your requirements as currently stated. The "longest leftmost" behavior could still get in the way if there are e.g. straddling repetitions, like
this that more words this that more words
where in the general case regex alone cannot easily be made to always prefer the last possible match and tolerate arbitrary amounts of text after it.

Related

Regex for name with non-latin characters in python [duplicate]

For website validation purposes, I need first name and last name validation.
For the first name, it should only contain letters, can be several words with spaces, and has a minimum of three characters, but a maximum at top 30 characters. An empty string shouldn't be validated (e.g. Jason, jason, jason smith, jason smith, JASON, Jason smith, jason Smith, and jason SMITH).
For the last name, it should be a single word, only letters, with at least three characters, but at most 30 characters. Empty strings shouldn't be validated (e.g. lazslo, Lazslo, and LAZSLO).
Don't forget about names like:
Mathias d'Arras
Martin Luther King, Jr.
Hector Sausage-Hausen
This should do the trick for most things:
/^[a-z ,.'-]+$/i
OR Support international names with super sweet unicode:
/^[a-zA-ZàáâäãåąčćęèéêëėįìíîïłńòóôöõøùúûüųūÿýżźñçčšžÀÁÂÄÃÅĄĆČĖĘÈÉÊËÌÍÎÏĮŁŃÒÓÔÖÕØÙÚÛÜŲŪŸÝŻŹÑßÇŒÆČŠŽ∂ð ,.'-]+$/u
You make false assumptions on the format of first and last name. It is probably better not to validate the name at all, apart from checking that it is empty.
After going through all of these answers I found a way to build a tiny regex that supports most languages and only allows for word characters. It even supports some special characters like hyphens, spaces and apostrophes. I've tested in python and it supports the characters below:
^[\w'\-,.][^0-9_!¡?÷?¿/\\+=##$%ˆ&*(){}|~<>;:[\]]{2,}$
Characters supported:
abcdefghijklmnopqrstwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
áéíóúäëïöüÄ'
陳大文
łŁőŐűŰZàáâäãåąčćęèéêëėįìíîïłńòóôöõøùúûüųū
ÿýżźñçčšžÀÁÂÄÃÅĄĆČĖĘÈÉÊËÌÍÎÏĮŁ
ŃÒÓÔÖÕØÙÚÛÜŲŪŸÝŻŹÑßÇŒÆČŠŽ.-
ñÑâê都道府県Федерации
আবাসযোগ্য জমির걸쳐 있는
I have created a custom regex to deal with names:
I have tried these types of names and found working perfect
John Smith
John D'Largy
John Doe-Smith
John Doe Smith
Hector Sausage-Hausen
Mathias d'Arras
Martin Luther King
Ai Wong
Chao Chang
Alzbeta Bara
My RegEx looks like this:
^([a-zA-Z]{2,}\s[a-zA-Z]{1,}'?-?[a-zA-Z]{2,}\s?([a-zA-Z]{1,})?)
MVC4 Model:
[RegularExpression("^([a-zA-Z]{2,}\\s[a-zA-Z]{1,}'?-?[a-zA-Z]{2,}\\s?([a-zA-Z]{1,})?)", ErrorMessage = "Valid Charactors include (A-Z) (a-z) (' space -)") ]
Please note the double \\ for escape characters
For those of you that are new to RegEx I thought I'd include a explanation.
^ // start of line
[a-zA-Z]{2,} // will except a name with at least two characters
\s // will look for white space between name and surname
[a-zA-Z]{1,} // needs at least 1 Character
\'?-? // possibility of **'** or **-** for double barreled and hyphenated surnames
[a-zA-Z]{2,} // will except a name with at least two characters
\s? // possibility of another whitespace
([a-zA-Z]{1,})? // possibility of a second surname
I have searched and searched and played and played with it and although it is not perfect it may help others making the attempt to validate first and last names that have been provided as one variable.
In my case, that variable is $name.
I used the following code for my PHP:
if (preg_match('/\b([A-Z]{1}[a-z]{1,30}[- ]{0,1}|[A-Z]{1}[- \']{1}[A-Z]{0,1}
[a-z]{1,30}[- ]{0,1}|[a-z]{1,2}[ -\']{1}[A-Z]{1}[a-z]{1,30}){2,5}/', $name)
# there is no space line break between in the above "if statement", any that
# you notice or perceive are only there for formatting purposes.
#
# pass - successful match - do something
} else {
# fail - unsuccessful match - do something
I am learning RegEx myself but I do have the explanation for the code as provided by RegEx buddy.
Here it is:
Assert position at a word boundary «\b»
Match the regular expression below and capture its match into backreference number 1
«([A-Z]{1}[a-z]{1,30}[- ]{0,1}|[A-Z]{1}[- \']{1}[A-Z]{0,1}[a-z]{1,30}[- ]{0,1}|[a-z]{1,2}[ -\']{1}[A-Z]{1}[a-z]{1,30}){2,5}»
Between 2 and 5 times, as many times as possible, giving back as needed (greedy) «{2,5}»
* I NEED SOME HELP HERE WITH UNDERSTANDING THE RAMIFICATIONS OF THIS NOTE *
Note: I repeated the capturing group itself. The group will capture only the last iteration. Put a capturing group around the repeated group to capture all iterations. «{2,5}»
Match either the regular expression below (attempting the next alternative only if this one fails) «[A-Z]{1}[a-z]{1,30}[- ]{0,1}»
Match a single character in the range between “A” and “Z” «[A-Z]{1}»
Exactly 1 times «{1}»
Match a single character in the range between “a” and “z” «[a-z]{1,30}»
Between one and 30 times, as many times as possible, giving back as needed (greedy) «{1,30}»
Match a single character present in the list “- ” «[- ]{0,1}»
Between zero and one times, as many times as possible, giving back as needed (greedy) «{0,1}»
Or match regular expression number 2 below (attempting the next alternative only if this one fails) «[A-Z]{1}[- \']{1}[A-Z]{0,1}[a-z]{1,30}[- ]{0,1}»
Match a single character in the range between “A” and “Z” «[A-Z]{1}»
Exactly 1 times «{1}»
Match a single character present in the list below «[- \']{1}»
Exactly 1 times «{1}»
One of the characters “- ” «- » A ' character «\'»
Match a single character in the range between “A” and “Z” «[A-Z]{0,1}»
Between zero and one times, as many times as possible, giving back as needed (greedy) «{0,1}»
Match a single character in the range between “a” and “z” «[a-z]{1,30}»
Between one and 30 times, as many times as possible, giving back as needed (greedy) «{1,30}»
Match a single character present in the list “- ” «[- ]{0,1}»
Between zero and one times, as many times as possible, giving back as needed (greedy) «{0,1}»
Or match regular expression number 3 below (the entire group fails if this one fails to match) «[a-z]{1,2}[ -\']{1}[A-Z]{1}[a-z]{1,30}»
Match a single character in the range between “a” and “z” «[a-z]{1,2}»
Between one and 2 times, as many times as possible, giving back as needed (greedy) «{1,2}»
Match a single character in the range between “ ” and “'” «[ -\']{1}»
Exactly 1 times «{1}»
Match a single character in the range between “A” and “Z” «[A-Z]{1}»
Exactly 1 times «{1}»
Match a single character in the range between “a” and “z” «[a-z]{1,30}»
Between one and 30 times, as many times as possible, giving back as needed (greedy) «{1,30}»
I know this validation totally assumes that every person filling out the form has a western name and that may eliminates the vast majority of folks in the world. However, I feel like this is a step in the proper direction. Perhaps this regular expression is too basic for the gurus to address simplistically or maybe there is some other reason that I was unable to find the above code in my searches. I spent way too long trying to figure this bit out, you will probably notice just how foggy my mind is on all this if you look at my test names below.
I tested the code on the following names and the results are in parentheses to the right of each name.
STEVE SMITH (fail)
Stev3 Smith (fail)
STeve Smith (fail)
Steve SMith (fail)
Steve Sm1th (passed on the Steve Sm)
d'Are to Beaware (passed on the Are to Beaware)
Jo Blow (passed)
Hyoung Kyoung Wu (passed)
Mike O'Neal (passed)
Steve Johnson-Smith (passed)
Jozef-Schmozev Hiemdel (passed)
O Henry Smith (passed)
Mathais d'Arras (passed)
Martin Luther King Jr (passed)
Downtown-James Brown (passed)
Darren McCarty (passed)
George De FunkMaster (passed)
Kurtis B-Ball Basketball (passed)
Ahmad el Jeffe (passed)
If you have basic names, there must be more than one up to five for the above code to work, that are similar to those that I used during testing, this code might be for you.
If you have any improvements, please let me know. I am just in the early stages (first few months of figuring out RegEx.
Thanks and good luck,
Steve
I've tried almost everything on this page, then I decided to modify the most voted answer which ended up working best. Simply matches all languages and includes .,-' characters.
Here it is:
/^[\p{L} ,.'-]+$/u
First name would be
"([a-zA-Z]{3,30}\s*)+"
If you need the whole first name part to be shorter than 30 letters, you need to check that seperately, I think. The expression ".{3,30}" should do that.
Your last name requirements would translate into
"[a-zA-Z]{3,30}"
but you should check these. There are plenty of last names containing spaces.
As maček said:
Don't forget about names like:
Mathias d'Arras
Martin Luther King, Jr.
Hector Sausage-Hausen
and to remove cases like:
..Mathias
Martin king, Jr.-
This will cover more cases:
^([a-z]+[,.]?[ ]?|[a-z]+['-]?)+$
This regex work for me (was using in Angular 8) :
([a-zA-Z',.-]+( [a-zA-Z',.-]+)*){2,30}
It will be invalid if there is:-
Any whitespace start or end of the name
Got symbols e.g. #
Less than 2 or more than 30
Example invalid First Name (whitespace)
Example valid First Name :
I'm working on the app that validates International Passports (ICAO). We support only english characters. While most foreign national characters can be represented by a character in the Latin alphabet e.g. è by e, there are several national characters that require an extra letter to represent them such as the German umlaut which requires an ‘e’ to be added to the letter e.g. ä by ae.
This is the JavaScript Regex for the first and last names we use:
/^[a-zA-Z '.-]*$/
The max number of characters on the international passport is up to 31.
We use maxlength="31" to better word error messages instead of including it in the regex.
Here is a snippet from our code in AngularJS 1.6 with form and error handling:
class PassportController {
constructor() {
this.details = {};
// English letters, spaces and the following symbols ' - . are allowed
// Max length determined by ng-maxlength for better error messaging
this.nameRegex = /^[a-zA-Z '.-]*$/;
}
}
angular.module('akyc', ['ngMessages'])
.controller('PassportController', PassportController);
.has-error p[ng-message] {
color: #bc111e;
}
.tip {
color: #535f67;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
<script src="https://code.angularjs.org/1.6.6/angular-messages.min.js"></script>
<main ng-app="akyc" ng-controller="PassportController as $ctrl">
<form name="$ctrl.form">
<div name="lastName" ng-class="{ 'has-error': $ctrl.form.lastName.$invalid} ">
<label for="pp-last-name">Surname</label>
<div class="tip">Exactly as it appears on your passport</div>
<div ng-messages="$ctrl.form.lastName.$error" ng-if="$ctrl.form.$submitted" id="last-name-error">
<p ng-message="required">Please enter your last name</p>
<p ng-message="maxlength">This field can be at most 31 characters long</p>
<p ng-message="pattern">Only English letters, spaces and the following symbols ' - . are allowed</p>
</div>
<input type="text" id="pp-last-name" ng-model="$ctrl.details.lastName" name="lastName"
class="form-control" required ng-pattern="$ctrl.nameRegex" ng-maxlength="31" aria-describedby="last-name-error" />
</div>
<button type="submit" class="btn btn-primary">Test</button>
</form>
</main>
Read almost all highly voted posts (only some are good). After understanding the problem in detail & doing research, here are the tight regexes:
1). ^[A-Z][a-z]*(([,.] |[ '-])[A-Za-z][a-z]*)*(\.?)$
name Z is allowed contrary to the assumption made by some in the thread.
No leading or trailing spaces are allowed, empty string is NOT allowed, string containing only spaces is NOT allowed
Supports English alphabets only
Supports hyphens (Some-Foobarbaz-name, Some foobarbaz-Name), apostrophes (David D'Costa, David D'costa, David D'costa R'Costa p'costa), periods (Dr. L. John, Robert Downey Jr., Md. K. P. Asif) and commas (Martin Luther, Jr.).
First alphabet of only the first word of a name MUST be capital.
NOT Allowed: John sTeWaRT, JOHN STEWART, Md. KP Asif, John Stewart PhD
Allowed: John Stewart, John stewart, Md. K P Asif
you can easily modify this condition.
If you also want to allow names like Queen Elizabeth 2 or Henry IV:
2). ^[A-Z][a-z]*(([,.] |[ '-])[A-Za-z][a-z]*)*([.]?| (-----)| [1-9][0-9]*)$
replace ----- with roman numeral's regex (which itself is long) OR you can use this alternative regex which is based on KISS philosophy [IVXLCDM]+ (here I, V, X, ... in ANY random order will satisfy the regex).
I personally suggest to use this regex:
3). ^[A-Z][a-z]*(([,.] |[ '-])[A-Za-z][a-z]*)*(\.?)( [IVXLCDM]+)?$
Feel free to try this regex HERE & make any modifications of your choice.
I have provided with tight regex which covers every possible name I found on my research with no bug. Modify these regexes to relax some of the unwanted constraints.
[UPDATE - March, 2022]
Here are 4 more regexes:
^[A-Za-z]+(([,.] |[ '-])[A-Za-z]+)*([.,'-]?)$
^((([,.'-]| )(?<!( {2}|[,.'-]{2})))*[A-Za-z]+)+[,.'-]?$
^( ([A-Za-z,.'-]+|$))+|([A-Za-z,.'-]+( |$))+$
^(([ ,.'-](?<!( {2}|[,.'-]{2})))*[A-Za-z])+[ ,.'-]?$
It's been a while since I looked back at these 4 regexes so I forgot their specifications. These 4 regexes are not tight, unlike the previous ones but do the job very well. These regexes distinguish 3 parts of a name: English alphabet, space and special character. Which one you need out of these 4 depends on your answer (Yes/No) to these questions:
have at least 1 alphabet?
can start with a space or a special character?
can end with a space or a special character?
are 2 consecutive spaces allowed?
are 2 consecutive special characters allowed?
Note: name validation should ONLY serve as a warning NOT a necessity a name should fulfill because there is no fixed naming pattern, if there is one it can change overnight and thus, any tight regex you come across will become obsolete somewhere in future.
There is one issue with the top voted answer here which recommends this regex:
/^[a-z ,.'-]+$/i
It takes spaces only as a valid name!
The best solution in my opinion is to add a negative look forward to the beginning:
^(?!\s)([a-z ,.'-]+)$/i
I use:
/^(?:[\u00c0-\u01ffa-zA-Z'-]){2,}(?:\s[\u00c0-\u01ffa-zA-Z'-]{2,})+$/i
And test for maxlength using some other means
I didn't find any answer helpful for me simply because users can pick a non-english name and simple regex are not helpful. In fact it's actually very hard to find the right expression that works for all languages.
Instead, I picked a different approach and negated all characters that should not be in the name for the valid match. Below pattern negates numerical, special characters, control characters and '\', '/'
Final regex
without punctuations: ["] ['] [,] [.], etc. :
^([^\p{N}\p{S}\p{C}\p{P}]{2,20})$
with punctuations:
^([^\p{N}\p{S}\p{C}\\\/]{2,20})$
With this, all these names are valid:
alex junior
沐宸
Nick
Sarah's Jane ---> with punctuation support
ביממה
حقیقت
Виктория
And following names become invalid:
🤣 Maria
k
١١١١١
123John
This means all names that don't have numerical characters, emojis, \ and are between 2-20 characters are allowed. You can edit the above regex if you want to add more characters to exclusion list.
To get more information about available patterns to include / exclude checkout this:
https://www.regular-expressions.info/unicode.html#prop
^\p{L}{2,}$
^ asserts position at start of a line.
\p{L} matches any kind of letter from any language
{2,} Quantifier — Matches between 2 and unlimited times, as many times as possible, giving back as needed (greedy)
$ asserts position at the end of a line
So it should be a name in any language containing at least 2 letters(or symbols) without numbers or other characters.
If you are searching a simplest way, just check almost 2 words.
/^[^\s]+( [^\s]+)+$/
Valid names
John Doe
pedro alberto ch
Ar. Gen
Mathias d'Arras
Martin Luther King, Jr.
No valid names
John
陳大文
For simplicities sake, you can use:
(.*)\s(.*)
The thing I like about this is that the last name is always after the first name, so if you're going to enter this matched groups into a database, and the name is John M. Smith, the 1st group will be
John M., and the 2nd group will be Smith.
So, with customer we create this crazy regex:
(^$)|(^([^\-!#\$%&\(\)\*,\./:;\?#\[\\\]_\{\|\}¨ˇ“”€\+<=>§°\d\s¤®™©]| )+$)
For first and last names theres are really only 2 things you should be looking for:
Length
Content
Here is my regular expression:
var regex = /^[A-Za-z-,]{3,20}?=.*\d)/
1. Length
Here the {3,20} constrains the length of the string to be between 3 and 20 characters.
2. Content
The information between the square brackets [A-Za-z] allows uppercase and lowercase characters. All subsequent symbols (-,.) are also allowed.
The following expression will work on any language supported by UTF-16 and will ensure that there's a minimum of two components to the name (i.e. first + last), but will also allow any number of middle names.
/^(\S+ )+\S+$/u
At the time of this writing it seems none of the other answers meet all of that criteria. Even ^\p{L}{2,}$, which is the closest, falls short because it will also match "invisible" characters, such as U+FEFF (Zero Width No-Break Space).
Try these solutions, for maximum compatibility, as I have already posted here:
JavaScript:
var nm_re = /^(?:((([^0-9_!¡?÷?¿/\\+=##$%ˆ&*(){}|~<>;:[\]'’,\-.\s])){1,}(['’,\-\.]){0,1}){2,}(([^0-9_!¡?÷?¿/\\+=##$%ˆ&*(){}|~<>;:[\]'’,\-. ]))*(([ ]+){0,1}(((([^0-9_!¡?÷?¿/\\+=##$%ˆ&*(){}|~<>;:[\]'’,\-\.\s])){1,})(['’\-,\.]){0,1}){2,}((([^0-9_!¡?÷?¿/\\+=##$%ˆ&*(){}|~<>;:[\]'’,\-\.\s])){2,})?)*)$/;
HTML5:
<input type="text" name="full_name" id="full_name" pattern="^(?:((([^0-9_!¡?÷?¿/\\+=##$%ˆ&*(){}|~<>;:[\]'’,\-.\s])){1,}(['’,\-\.]){0,1}){2,}(([^0-9_!¡?÷?¿/\\+=##$%ˆ&*(){}|~<>;:[\]'’,\-. ]))*(([ ]+){0,1}(((([^0-9_!¡?÷?¿/\\+=##$%ˆ&*(){}|~<>;:[\]'’,\-\.\s])){1,})(['’\-,\.]){0,1}){2,}((([^0-9_!¡?÷?¿/\\+=##$%ˆ&*(){}|~<>;:[\]'’,\-\.\s])){2,})?)*)$" required>
This is what I use.
This regex accepts only names with minimum characters, from A-Z a-z ,space and -.
Names example:
Ionut Ionete, Ionut-Ionete Cantemir, Ionete Ionut-Cantemirm Ionut-Cantemir Ionete-Second
The limit of name's character is 3. If you want to change this, modify {3,} to {6,}
([a-zA-Z\-]+){3,}\s+([a-zA-Z\-]+){3,}
This seems to do the job for me:
[\S]{2,} [\S]{2,}( [\S]{2,})*
I usually write:
return /^[a-zA-Z\-\s\.\'\`\u00E0-\u00FC]+$/.test(firstName);
Fullname with only one whitespace:
^[a-zA-Z'\-\pL]+(?:(?! {2})[a-zA-Z'\-\pL ])*[a-zA-Z'\-\pL]+$
A simple function using preg_match in php
<?php
function name_validation($name) {
if (!preg_match("/^[a-zA-Z ]*$/", $name) === false) {
echo "$name is a valid name";
} else {
echo "$name is not a valid name";
}
}
//Test
name_validation('89name');
?>
If you want the whole first name to be between 3 and 30 characters with no restrictions on individual words, try this :
[a-zA-Z ]{3,30}
Beware that it excludes all foreign letters as é,è,à,ï.
If you want the limit of 3 to 30 characters to apply to each individual word, Jens regexp will do the job.
var name = document.getElementById('login_name').value;
if ( name.length < 4 && name.length > 30 )
{
alert ( 'Name length is mismatch ' ) ;
}
var pattern = new RegExp("^[a-z\.0-9 ]+$");
var return_value = var pattern.exec(name);
if ( return_value == null )
{
alert ( "Please give valid Name");
return false;
}

Regex to get any numbers after the occurrence of a string in a line

Hi guys im trying to get the the substring as well as the corresponding number from this string
text = "Milk for human consumption may be taken only from cattle from 80 hours after the last treatment."
I want to select the word milk and the corresponding number 80 from this sentence. This is part of a larger file and i want a generic solution to get the word milk in a line and then the first number that occurs after this word anywhere in that line.
(Milk+)\d
This is what i came up with thinking that i can make a group milk and then check for digits but im stumped how to start a search for numbers anywhere on line and not just immediately after the word milk. Also is there any way to make the search case insensitive?
Edit: im looking to get both the word and the number if possible eg: "milk" "80" and using python
/(?<!\p{L})([Mm]ilk)(?!p{L})\D*(\d+)/
This matches the following strings, with the match and the contents of the two capture groups noted.
"The Milk99" # "Milk99" 1:"Milk" 2:"99"
"The milk99 is white" # "milk99" 1:"milk" 2:"99"
"The 8 milk is 99" # "milk is 99" 1:"milk" 2:"99"
"The 8milk is 45 or 73" # "milk is 45" 1:"milk" 2:"45"
The following strings are not matched.
"The Milk is white"
"The OJ is 99"
"The milkman is 37"
"Buttermilk is 99"
"MILK is 99"
This regular expression could be made self-documenting by writing it in free-spacing mode:
/
(?<!\p{L}) # the following match is not preceded by a Unicode letter
([Mm]ilk) # match 'M' or 'm' followed by 'ilk' in capture group 2
(?!p{L}) # the preceding match is not followed by a Unicode letter
\D* # match zero or more characters other than digits
(\d+) # match one or more digits in capture group 2
/x # free-spacing regex definition mode
\D* could be replaced with .*?, ? making the match non-greedy. If the greedy variant were used (.*), the second capture group for "The 8milk is 45 or 73" would contain "3".
To match "MILK is 99", change ([Mm]ilk) to (?i)(milk).
This seems to work in java (I overlooked that the questioner wanted python or the question was later edited) like you want to:
String example =
"Test 40\n" +
"Test Test milk for human consumption may be taken only from cattle from hours after the last treatment." +
"\nTest Milk for human consumption may be taken only from cattle from 80 hours after the last treatment." +
"\nTest miLk for human consumption may be taken only from cattle from 80 hours after the last treatment.";
Matcher m = Pattern.compile("((?i)(milk).*?(\\d+).*\n?)+").matcher(example);
m.find();
System.out.print(m.group(2) + m.group(3));
Look at how it tests whether the word "milk" appears in a case insensitive manner anywhere before a number in the exact same line and only prints these both. It also prints only the first found occurence (making it find all occurencies is also possible pretty easily just by a little modifications of the given code).
I hope the way it extracts these both things from a matching pattern is in the sense of your task.
You should try this one
(Milk).*?(\d+)
Based on your language, you can also specify a case-insensitive search. Example in JS: /(Milk).*?(\d+)/i, the final i makes the search case insensitive.
Note the *?, the most important part ! This is a lazy iteration. In other words, it reads any char, but as soon as it can stop and process the next instruction successfully then it does. Here, as soon as you can read a digit, you read it. A simple * would have returned the last number from this line after Milk instead

Regex for for Phone Numbers allowing for only 6 to 20 characters

Regex beginner here. I've been trying to tackle this rule for phone numbers to no avail and would appreciate some advice:
Minimum 6 characters
Maximum 20 characters
Must contain numbers
Can contain these symbols ()+-.
Do not match if all the numbers included are the same (ie. 111111)
I managed to build two of the following pieces but I'm unable to put them together.
Here's what I've got:
(^(\d)(?!\1+$)\d)
([0-9()-+.,]{6,20})
Many thanks in advance!
I'd go about it by first getting a list of all possible phone numbers (thanks #CAustin for the suggested improvements):
lst_phone_numbers = re.findall('[0-9+()-]{6,20}',your_text)
And then filtering out the ones that do not comply with statement 5 using whatever programming language you're most comfortable.
Try this RegEx:
(?:([\d()+-])(?!\1+$)){6,20}
Explained:
(?: creates a non-capturing group
(\d|[()+-]) creates a group to match a digit, parenthesis, +, or -
(?!\1+$) this will not return a match if it matches the value found from #2 one or more times until the end of the string
{6,20} requires 6-20 matches from the non-capturing group in #1
Try this :
((?:([0-9()+\-])(?!\2{5})){6,20})
So , this part ?!\2{5} means how many times is allowed for each one from the pattern to be repeated like this 22222 and i put 5 as example and you could change it as you want .

Regex for validation of a street number

I'm using an online tool to create contests. In order to send prizes, there's a form in there asking for user information (first name, last name, address,... etc).
There's an option to use regular expressions to validate the data entered in this form.
I'm struggling with the regular expression to put for the street number (I'm located in Belgium).
A street number can be the following:
1234
1234a
1234a12
begins with a number (max 4 digits)
can have letters as well (max 2 char)
Can have numbers after the letter(s) (max3)
I came up with the following expression:
^([0-9]{1,4})([A-Za-z]{1,2})?([0-9]{1,3})?$
But the problem is that as letters and second part of numbers are optional, it allows to enter numbers with up to 8 digits, which is not optimal.
1234 (first group)(no letters in the second group) 5678 (third group)
If one of you can tip me on how to achieve the expected result, it would be greatly appreciated !
You might use this regex:
^\d{1,4}([a-zA-Z]{1,2}\d{1,3}|[a-zA-Z]{1,2}|)$
where:
\d{1,4} - 1-4 digits
([a-zA-Z]{1,2}\d{1,3}|[a-zA-Z]{1,2}|) - optional group, which can be
[a-zA-Z]{1,2}\d{1,3} - 1-2 letters + 1-3 digits
or
[a-zA-Z]{1,2} - 1-2 letters
or
empty
\d{0,4}[a-zA-Z]{0,2}\d{0,3}
\d{0,4} The first groupe matches a number with 4 digits max
[a-zA-Z]{0,2} The second groupe matches a char with 2 digit in max
\d{0,3} The first groupe matches a number with 3 digits max
You have to keep the last two groups together, not allowing the last one to be present, if the second isn't, e.g.
^\d{1,4}(?:[a-zA-z]{1,2}\d{0,3})?$
or a little less optimized (but showing the approach a bit better)
^\d{1,4}(?:[a-zA-z]{1,2}(?:\d{1,3})?)?$
As you are using this for a validation I assumed that you don't need the capturing groups and replaced them with non-capturing ones.
You might want to change the first number check to [1-9]\d{0,3} to disallow leading zeros.
Thank you so much for your answers ! I tried Sebastian's solution :
^\d{1,4}(?:[a-zA-z]{1,2}\d{0,3})?$
And it works like a charm ! I still don't really understand what the ":" stand for, but I'll try to figure it out next time i have to fiddle with Regex !
Have a nice day,
Stan
The first digit cannot be 0.
There shouldn't be other symbols before and after the number.
So:
^[1-9]\d{0,3}(?:[a-zA-Z]{1,2}\d{0,3})?$
The ?: combination means that the () construction does not create a matching substring.
Here is the regex with tests for it.

Regex to validate only US and India retail number

I am trying to get a regex which serves below requirements:
Validates US, India retail phone number
Excludes special purpose/business purpose phone numbers in both countries. I.e. starting with 800, 888, 877, and 866, 900, at least 10 digits for US, there can be more guidelines but above is just for example.
It should validate special chars if any like (, ), +, 1, 0 if included but satisfies all this points than should be a valid phone number.
If preceded by STD, ISD consider it as valid.
Landline, mobile both should be valid.
I looked whether some came across the same requirements, but the solutions I am getting serve different requirements and not exactly the one I am looking for.
Without a definitive exclusion/inclusion list of the phone numbers you want to match, here is a "template" regular expression that you could use to match US numbers:
(?:^|\b)(\+?1[ -.\/]?)?\(?(?!37|950|958|959|96|976)[2-9]([0-8])(?!\2)\d(?:\) ?|[ -.\/])?[2-9](?!11)\d\d[ -.]?\d{4}(?:$|\b)
A break-down:
(?:^|\b): Start of string or break. This prevents, for example, the match of digits to start in the middle of a longer series of digits;
(\+?1[ -.\/]?)?: this matches an optional prefix of the US country code (i.e. 1), and accepts values like +1, 1/, +1, 1;
\(?: an optional opening bracket for the region code;
(?!37|950|958|959|96|976): exclusion list of region codes. When only 2 digits are given, any region code starting with those is rejected -- you'll need to extend this list to identify other "special business" phone numbers you want to exclude;
[2-9]: first digit of region code; cannot be 0 or 1;
([0-8]): second digit of region code; cannot be 9;
(?!\2)\d: third digit of region code; cannot be the same as the second digit (\2 refers to the second match group);
(?:\) ?|[ -.\/])?: optional separator: ),-,.,/, or space. If ), it can optionally be followed by a space;
[2-9]: first digit of exchange code; cannot be 0 or 1;
(?!11): exclusion for second and third digits of exchange code -- they cannot both be 1 at the same time;
\d\d: second and third digit of exchange code; no further limitations;
[ -.]?: optional separator; can be -, . or space;
\d{4}: four digit customer number; no restrictions.
(?:$|\b): End of string or break. This prevents, for example, the match of digits to stop in the middle of a longer series of digits;
Here is an online regex test.
I suppose with the above as inspiration, you could fine-tune it to your expectations, and add the Indian formats in the same manner. You can use the | operator to separate the two sub-regular expressions you will have, like (US|IND), where you need to replace those two arguments by real expressions of course.
To capture also the prefix STD or ISD, you can insert the following in the above regex, right after the break test:
(?:STD\b\s*|ISD\b\s*|)
...which matches these optional words followed by optional spaces.
However, the complexity of the final regex will increase the more precise you want to match and exclude invalid numbers. For example, if you would want to validate against the All India STD Code List, then your regular expression would get very long and hard to manage.