preg_match() or similar function for checking currency - php

1.449,00
1.000.000,55
19,90
etc
etc
I know what I listed above are very variable but there are possibilities for currency. I'm looking for a preg_match() example or any other function to deal with possible cases above. I tried with example below but it is not working properly. Any chance given me a most appropriate pattern for it?
if (! preg_match('/^[0-9.,]$/', $currency)) { echo 'No good.'; }

Something like this should work:
/^((?:\d{1,3}[,\.]?)+\d*)$/
This matches:
^ - Start of string
( - Capture the following:
(?:
\d{1,3} - One to three digits
[,\.]? - And an optional separator (comma or period)
)+ - One or more times
\d* - Zero or more digits
)
$ - End of string
It works by iteratively matching everything to the left side of the separator (if it's present), and then has \d* to pick up any optional fractions of currency.
You can see it passes all of your tests.
Edit: An updated regex looks like this:
^((?:\d\.\d{3}\.|\d{1,3}\.)?\d{1,3},\d{1,2})$
Where we match either:
\d\.\d{3}\. - One digit, a period, three digits, a period, OR
\d{1,3}\. - One and three digits, a period
None of the above (because of the ?)
Then, we match:
\d{1,3}, - One to three digits and a comma, followed by
\d{1,2} - One or two digits

Add + after the ] to allow more than just one character.

Related

RegularExpression with currency $ US or Canadian. Validating

^\$?(\d{1,3},?(\d{3},?)*\d{3}(\.\d{0,2})?|\d{1,3}(\.\d{0,2})?|\.\d{1,2}?)$
I actually found this to help me to validate the amount of $. The problem is that I want to have a limited amount to validate between 0$ and 99.99$. also amounts like 01.20 and 10.1 are not acceptable but 1.20$ 10.10 are.
Is there something I could modify on this regex.
Also this is for the use of my php code. I know I need to put one more backlash on the regex to make it work on php. thanks.
See regex in use here
^(?:\d{1,2}(?:\.\d{2})?|\.\d{2})\$$
^ Assert position at the start of the line
(?:\d{1,2}(?:\.\d{2})?|\.\d{2}) Match either of the following options
\d{1,2}(?:\.\d{2})? Option 1
\d{1,2} Match a digit one or two times
(?:\.\d{2})? Optionally match a decimal point followed by exactly two digits
\.\d{2} Option 2. Match a decimal point followed by exactly two digits
\$ Match $ literally
$ Assert position at the end of the line
Here is my suggestion:
^(?:0|[1-9]\d{0,2})(?:,?\d{3})*(?:\.\d{2})?\$$
^ asserts position at start of a line
(?:0|[1-9]\d{0,2}) matches either a 0 or a non-zero digit once followed by an optional digit
(?:,?\d{3})* matches an optional thousands separator followed by three digits zero or more times
(?:\.\d{2})? optionally matches a decimal place followed by two digits
\$ literally matches the dollar sign symbol
$ asserts position at the end of a line
Fiddle: Live Demo

regex patterns - noob in PHP

I have been testing and googling but still could'nt work out pattern to validate comma separated numbers.
9 digits long, numbers only, no spaces, leading number for each digit cannot be zero
Tried
^(?:\s*\d{9}\s*(?:,|$))+$
but no go
Note that commas are required since the input file should between 3 up to 20 (max) comma separated integers
You mentioned that there should be no spaces, but you used \s* (0+ whitespaces) in your pattern. Also, (?:,|$) matches a , or end of string, so your pattern allows a trailing ,.
I suggest using
^[1-9]\d{8}(?:,[1-9]\d{8}){2,19}$
See the regex demo
Details:
^ - start of string
[1-9] - the first digit of the 9-digit number cannot be zero, 1 to 9 only
\d{8} - the 8 remaining digits of the number
(?:,[1-9]\d{8}){2,19} - 2 to 19 (in total, 3 to 20) occurrences of
, - comma
[1-9]\d{8}){2,19} - see above
$ - end of string.
preg_match('=^[1-9][0-9,]*$=', $x); should do it, unless you're saying the number must be 9 digits long (with optional commas? or are the commas required?), in which case try something like preg_match('=^[1-9][0-9]{2},?[0-9]{3},?[0-9]{3}$=', $x);

Merge two regex and match strings but not with period (or dot or full stop)

I'm using PHP. I need to validate the following kind of strings:
B223213FCF#COM
B90TY13AAA#DE
232342342X#CO.UK
Which patterns is:
"B" followed by 2 digits and 7 alphanumeric values
9 digits and as tenth character either a "X" or another digit
After the # the following domain extensions are accepted:
com.au, ca, cn, com, de, es, fr, in, it, co.jp, com.mx, nl, co.uk
I managed to work out the following two regex which somehow work:
/B[0-9]{2}[0-9A-Z]{7}|[0-9]{9}(X|0-9])
#(com\.au|ca|cn|com|de|es|fr|in|it|co\.jp|com\.mx|nl|co\.uk)/i
The issues I'm facing are:
I don't understand how to merge the two regex in a single one
The second regex needs to be fixed to not match dots as in this case:
B223213FCF#COM.
because the above string (with the dot at the end) still validates. The domain extension must be considered as exact word I suppose.
You can merge the two regexps as
^(?:B\d{2}\w{7}|\d{9}X)#(?:co\.(?:uk|jp)|com(?:\.(?:au|mx))?|c[an]|de|es|fr|i[nt]|nl)$
See the regex demo
I introduced anchors ^ and $ to make sure the pattern is applied to the entire string, added two alternatives before # ((?:B\d{2}\w{7} and \d{9}X)), and shrunk the TLDs to make the regex more efficient (since that way fewer backtracking steps are necessary).
The regex matches:
^ - start of string
(?:B\d{2}\w{7}|\d{9}X) - two alternatives:
B\d{2}\w{7} - B followed with 2 digits followed with 2 word characters
| - or...
\d{9}X - nine digits followed with X
# - a literal # sign
(?:co\.(?:uk|jp)|com(?:\.(?:au|mx))?|c[an]|de|es|fr|i[nt]|nl) - the list of TLD alternatives
$ - end of string
NOTE
If the first part up to # must be case sensitive and the second one should not, omit the general /i modifier at the end of the regex declaration and use the (?i:...) syntax to force the second part to be case insensitive:
'~^(?:B\d{2}\w{7}|\d{9}X)#(?i:co\.(?:uk|jp)|com(?:\.(?:au|mx))?|c[an]|de|es|fr|i[nt]|nl)$~'
See another regex demo

Match string that doesn't have number after letter

I've got a scenario as follows. Our systems needs to pull filters from a string passed in as a query parameter, but also throw a 404 error if the string isn't correctly formatted. So let's take the following three strings as an exmple:
pf0pt1000r
pfasdfadf
pf2000pt2100
By the application requirements, only #3 is supposed to match as a "valid" string. So my current regex to match that is /([a-z]+)(\d+)/. But this also matches #1, if not entirely, but it still matches.
My problem thus is twofold - I need 2 patterns, 1 that will match only the 3rd string in this list, and another that will match the "not-acceptable" strings 1 and 2. I believe there must be some way to "negate" a pattern (so then I'd technically only need one pattern, I'm assuming), but I'm not sure how exactly to do that.
Thanks for any help!
EDIT
For clarity's sake, let me explain. The "filter parameters" present here take the following structure - 1 or 2 letters, followed by a number of, well, numbers. That structure can repeat itself however many times. So for example, valid filter strings could be
pf100pt2000
pf100pt2000r2wp0to1
etc.
Invalid strings could be
pf10000pt2000r
pf3000pt2123wpno
... anything not following the structure above.
After clarifying the question:
^([a-zA-Z]{1,2}\d+)*$
Explanation:
[a-zA-Z] - a lower or upper case letter
{1,2} - one or two of those
\d+ - one or more digits
()* - the whole thing repeated any number of times
^$ - match the entire string from start(^) to end($)
You can use this regex for valid input:
^([a-zA-Z]+\d+)+$
RegEx Demo 1
To find invalid inputs use:
^(?!([a-zA-Z]+\d+)+$).+$
RegEx Demo 2
/^(?:(?:[a-z]+)(?:\d+))*$/
You were hella close, man. Just need to repeat that pattern over and over again till the end.
Change the * to a + to reject the empty string.
Oh, you had more specific requirements, try this:
/^(?:[a-z]{1,2}\d+)*$/
Broken down:
^ - Matches the start of the string an anchor
(?: - start a non-capturing group
[a-z] - A to Z. This you already had.
{1,2} - Repeat 1 or 2 times
\d+ - a digit or more You had this, too.
)* - Repeat that group ad nauseum
$ - Match the end of the string
If you only want digits at the end of the string, then
/\d$/
would do. \d = digit, $ = end of string.

php regex - find uppercase string with number and spaces in text

I want to write php regular expression to find uppercase string , which can also contain one number and spaces, from text.
For example from this text "some text to contain EXAM PL E 7STRING uppercase word" I want to get string- EXAM PL E 7STRING ,
found string should start and end only with uppercase, but in the middle, without uppercase letters can also contain(but not necessarily ) one number and spaces. So, regex should match any of these patterns
1) EXAMPLESTRING - just uppercase string
2) EXAMP4LESTRING - with number
3) EXAMPLES TRING - with space
4) EXAM PL E STRING - with more than one spaces
5) EXAMP LE4STRING - with number and space
6) EXAMP LE 4ST RI NG - with number and spaces
and with total length string should be equal or more than 4 letters
I wrote this regex '/[A-Z]{1,}([A-Z\s]{2,}|\d?)[A-Z]{1,}/', that can find first 4 patterns, but I can not figure it out to match also the last 2 patterns.
Thanks
There is a neat trick called a lookahead. It just checks what is following after the current position. That can be used to check for multiple conditions:
'/(?<![A-Z])(?=(?:[A-Z][\s\d]*){3}[A-Z])(?!(?:[A-Z\s]*\d){2})[A-Z][A-Z\s\d]*[A-Z]/'
The first lookaround is actually a lookbehind and checks that there is no previous uppercase letter. This is just a little speedup for strings that would fail the match anyway. The second lookaround (a lookahead) checks that there are at least four letters. The third one checks that there are no two digits. The rest just matches then a string of the allowed characters, starting and ending with an uppercase letter.
Note that in the case of two digits this will not match at all (instead of matching everything up to the second digit). If you do want to match in such a case, you could incorporate the "1 digit" rule into the actual match instead:
'/(?<![A-Z])(?=(?:[A-Z][\s\d]*){3}[A-Z])[A-Z][A-Z\s]*\d?[A-Z\s]*[A-Z]/'
EDIT:
As Ωmega pointed out, this will cause problems if there are less then four letters before the second digit, but more after that. This is actually quite tough, because the assertion needs to be, that there are more than 4 letters before the second digit. Since we do not know where the first digit occurs in those four letters, we have to check for all possible positions. For this I would do away with the lookaheads altogether, and simply provide the three different alternatives. (I will keep the lookbehind as an optimization for non-matching parts.)
'/(?<![A-Z])[A-Z]\s*(?:\d\s*[A-Z]\s*[A-Z]|[A-Z]\s*\d\s*[A-Z]|[A-Z]\s*[A-Z][A-Z\s]*\d?)[A-Z\s]*[A-Z]/'
Or here with added comments:
'/
(?<! # negative lookbehind
[A-Z] # current position is not preceded by a letter
) # end of lookbehind
[A-Z] # match has to start with uppercase letter
\s* # optional spaces after first letter
(?: # subpattern for possible digit positions
\d\s*[A-Z]\s*[A-Z]
# digit comes after first letter, we need two more letters before last one
| # OR
[A-Z]\s*\d\s*[A-Z]
# digit comes after second letter, we need one more letter before last one
| # OR
[A-Z]\s*[A-Z][A-Z\s]*\d?
# digit comes after third letter, or later, or not at all
) # end of subpattern for possible digit positions
[A-Z\s]* # arbitrary amount of further letters and whitespace
[A-Z] # match has to end with uppercase letter
/x'
That gives the same result on Ωmega's lengthy test input.
I suggest to use regex pattern
[A-Z][ ]*(\d)?(?(1)(?:[ ]*[A-Z]){3,}|[A-Z][ ]*(\d)?(?(2)(?:[ ]*[A-Z]){2,}|[A-Z][ ]*(\d)?(?(3)(?:[ ]*[A-Z]){2,}|[A-Z][ ]*(?:\d|(?:[ ]*[A-Z])+[ ]*\d?))))(?:[ ]*[A-Z])*
(see this demo).
[A-Z][ ]*(?:\d(?:[ ]*[A-Z]){2}|[A-Z][ ]*\d[ ]*[A-Z]|(?:[A-Z][ ]*){2,}\d?)[A-Z ]*[A-Z]
(see this demo)

Categories