How can I match numbers between 900 and 950?.
I have the following regex to match numbers 900-950 :
/9[0-5][0-9]{3}/
But it is also matching 955 in a string,
How can I fix it to match untill 900 to 950 only?
To match 900-950 number range, use
^9(?:[0-4][0-9]|50)$
Or, if it is inside a larger text
(?<!\d)9(?:[0-4][0-9]|50)(?!\d)
See this regex demo
The ^ is the start of string anchor, and $ is the end of string anchor.
The (?<!\d) is a negative lookbehind making sure the preceding symbol is not a digit. The (?!\d) is a negative lookahead that makes sure the next character is not a digit.
Using a non-capturing group (?:...) we avoid capturing what we do not need.
One more option: if the number is in-between non-word characters, you can leverage word boundaries:
\b9(?:[0-4][0-9]|50)\b
Note that I am using 9(?:[0-4][0-9]|50), not (?:9[0-4][0-9]|950). Although the second one is more readable, it is less effecient from the performance point of view since 9(?:[0-4][0-9]|50) involves less backtracking (i.e. it fails quicker if there is no match).
split it up into ORs:
/(9[0-4][0-9]|950)/
9[0-4][0-9] will match from 900 to 949
950 covers your 950 case without going over
if you want to make sure NOT to match anything else (like you might not want to match 1950 and might only want to match 950 on its own):
/(?<![0-9])(9[0-4][0-9]|950)(?![0-9])/
(?<![0-9]) means don't allow a number before and (?![0-9]) means don't allow a number after (negative look behind and ahead)
I think the easiest would be this:
/[^\d]9([0-4][0-9])|50[^\d]/
Related
Is it possible to write a regular expression that matches with digits that does not have integer on left or right side? If we have these strings:
a20c
20c
.20c
a20-
120
It should match the four first, but not the last one.
This regex patterns will match text that has the 20 somewhere in the middle and of which no other number is touching the 20. This could occur anywhere in the text, therefore matching DM11 20-B but not DM1120-B.
[^0-9]20[^0-9]
Or a little more condensed:
\D20\D
You can use ^\D{1}\d+\D{1}$
Olso you can test your regex here:
https://regex101.com/r/nU4jL1/2
You can use 2 lookarounds to make sure your digits are surrounded by non-digits:
(?<=\D)\d+|\d+(?=\D)
RegEx Demo
I have a piece of data, retrieved from the database and containing information I need. Text is entered in a free form so it's written in many different ways. The only thing I know for sure is that I'm looking for the first number after a given string, but after that certain string (before the number) can be any text as well.
I tried this (where mytoken is the string I know for sure its there) but this doesn't work.
/(mytoken|MYTOKEN)(.*)\d{1}/
/(mytoken|MYTOKEN)[a-zA-Z]+\d{1}/
/(mytoken|MYTOKEN)(.*)[0-9]/
/(mytoken|MYTOKEN)[a-zA-Z]+[0-9]/
Even mytoken can be written in capitals, lowercase or a mix of capitals and lowercase character. Can the expression be case insensitive?
You do not need any lazy matching since you want to match any number of non-digit symbols up to the first digit. It is better done with a \D*:
/(mytoken)(\D*)(\d+)/i
See the regex demo
The pattern details:
(mytoken) - Group 1 matching mytoken (case insensitively, as there is a /i modifier)
(\D*) - Group 2 matching zero or more characters other than a digit
(\d+) - Group 3 matching 1 or more digits.
Note that \D also matches newlines, . needs a DOTALL modifier to match across newlines.
You need to use a lazy quantifier. You can do that by putting a question mark after the star quantifier in the regex: .*?. Otherwise, the numbers will be matched by the dot operator until the last number, which will be matched by \d.
Regex: /(mytoken|MYTOKEN)(.*?)\d/
Regex demo
You can use the opposite:
/(mytoken|MYTOKEN)(\D+)(\d)/
This says: mytoken, followed by anything not a number, followed by a number. The (lazy) dot-star-soup is not always your best bet. The desired number will be in $3 in this example.
Below my regual expression:
preg_match('/^[\p{L}\p{N} #]+$/u', $string);
My goal is set minimum and maximum length of \p{L}, \p{N}, # and the whole string. I tried to putting {min, max} after \p{L} and after each part but it doesn't work.
You can set the min and max length to a pattern with the help of limiting quantifiers right after the subpattern that you need to repeat.
Here we need to use a trick to make sure we can count non-consecutive subpatterns. It can be done with negative character classes and look-aheads in the beginning.
Here is an example of the regex for *at least 4 letters \p{L}, at least 5 and 6 max numbers \p{N}, and at least three #:
^(?=(?:[^\n\p{L}]*\p{L}){4}[^\n\p{L}]*$)(?=(?:[^\n\p{N}]*\p{N}){5,6}[^\n\p{N}]*$)(?=(?:[^\n#]*#){3}[^\n#]*$)[\p{L}\p{N} #]+$
Here is a demo
Note that \n can be removed if you are not planning to use multiline mode (m flag).
The 3 conditions are inside look-aheads:
(?=(?:[^\n\p{L}]*\p{L}){4}[^\n\p{L}]*$) - This lookahead matches (from the beginning of input string) any sequence that is not letters and then a letter 4 times (you may set any other limits here, and then looks for non-letters up to the end (if it finds more, it fails).
(?=(?:[^\n\p{N}]*\p{N}){5,6}[^\n\p{N}]*$) - a similar lookahead, but now, we are matching non-digits + a digit 5 or 6 times, and make sure there are no numbers later.
(?=(?:[^\n#]*#){3}[^\n#]*$) - same logic for #.
If you need to only set a minimum threshold, you do not need those negated character classes at the end of a lookahead, e.g. (?=(?:[^\n#]*#){3}) will match 3 or more #, it will just require 3 #s.
I have to create regex to match ugly abbreviations and numbers. These can be one of following "formats":
1) [any alphabet char length of 1 char][0-9]
2) [double][whitespace][2-3 length of any alphabet char]
I tried to match double:
preg_match("/^-?(?:\d+|\d*\.\d+)$/", $source, $matches);
But I coldn't get it to select following example: 1.1 AA My test title. What is wrong with my regex and how can I add those others to my regex too?
In your regex you say "start of string, followed by maybe a - followed by at least one digit or followed by 0 or more digits, followed by a dot and followed by at least one digit and followed by the end of string.
So you regex could match for example.. 4.5, -.1 etc. This is exactly what you tell it to do.
You test input string does not match since there are other characters present after the number 1.1 and even if it somehow magically matched your "double" matching regex is wrong.
For a double without scientific notation you usually use this regex :
[-+]?\b[0-9]+(\.[0-9]+)?\b
Now that we have this out of our way we need a whitespace \s and
[2-3 length of alphabet]
Now I have no idea what [2-3 length of alphabet] means but by combining the above you get a regex like this :
[-+]?\b[0-9]+(\.[0-9]+)?\b\s[2-3 length of alphabet]
You can also place anchors ^$ if you want the string to match entirely :
^[-+]?\b[0-9]+(\.[0-9]+)?\b\s[2-3 length of alphabet]$
Feel free to ask if you are stuck! :)
I see multiple issues with your regex:
You try to match the whole string (as a number) by the anchors: ^ at the beginning and $ at the end. If you don't want that, remove those.
The number group is non-catching. It will be checked for matches, but those won't be added to $matches. That's because of the ?: internal options you set in (?:...). Remove ?: to make that group catching.
You place the shorter digit-pattern before the longer one. If you swap the order, the regex engine will look for it first and on success prefer it over the shorter one.
Maybe this already solves your issue:
preg_match("/-?(\d*\.\d+|\d+)/", $source, $matches);
Demo
I'm letting users enter GPS values through a form, they all have the same form, some examples:
49.082243,19.302628
48.234142,19.200423
49.002524,19.312578
I want to check the entered value using PHP (using preg_match(), I guess), but as I'm not good in regex expressions (oh, dumb me, I should finally learn it, I know), I don't know how to write the expression.
Obviously it should be:
2x (numbers), 1x (dot), 6x (numbers), 1x (comma), 2x (numbers), 1x (dot), 6x (numbers)
Any suggestions how to write this in regex?
The other answers I see don't take into account that longitude goes from -180 to 180 and latitude goes from -90 to 90.
The proper regex for this would be (assuming the order is "latitude, longitude"):
/^(-?[1-8]?\d(?:\.\d{1,6})?|90(?:\.0{1,6})?),(-?(?:1[0-7]|[1-9])?\d(?:\.\d{1,6})?|180(?:\.0{1,6})?)$/
This regex covers having no less than -90 and no more than 90 for latitude as well as no less than -180 and no more than 180 for longitude while allowing them to put in whole numbers as well as any number of decimal places from 1 to 6, if you want to allow greater precision just change {1,6} to {1,x} where x is the number of decimal place
Also, if you capture on group 1 you get the latitude and a capture on group 2 gets the longitude.
Something like:
/^(-?\d{1,2}\.\d{6}),(-?\d{1,2}\.\d{6})$/
^ anchors at the start of input
-? allows for, but does not require, a negative sign
\d{1,2} requires 1 or 2 decimal digits
\. requires a decimal point
\d{6} requires exactly 6 decimal digits
, matches a single comma
(repeat the first 5 bullets)
$ anchors at the end of input
I have included capturing parentheses to allow you to extract the individual coordinates. Feel free to omit them if you don't need that.
All-around useful regex reference: http://www.regular-expressions.info/reference.html
/$-?\d{2}\.\d{6},-?\d{2}\.\d{6}^/
Expanding on the other answer:
/^-?\d\d?\.\d+,-?\d\d?\.\d+$/
Based on your example, this will do it:
if (preg_match('/(-?[\d]{2}\.[\d]{6},?){2}/', $coords)) {
# Successful match
} else {
# Match attempt failed
}
Explanation:
( # Match the regular expression below and capture its match into backreference number 1
- # Match the character “-” literally
? # Between zero and one times, as many times as possible, giving back as needed (greedy)
[\d] # Match a single digit 0..9
{2} # Exactly 2 times
\. # Match the character “.” literally
[\d] # Match a single digit 0..9
{6} # Exactly 6 times
, # Match the character “,” literally
? # Between zero and one times, as many times as possible, giving back as needed (greedy)
){2} # Exactly 2 times