RegEx not fully correct [duplicate] - php

I want user only input 0-9 and only once "."
patt = /[^0-9(.{1})]/
1.2222 -> true
1.2.2 -> false (only once '.')
help me , thank !

/^-?(?:\d+|\d*\.\d+)$/
This matches normal floats e.g. 3.14, shorthands for decimal part only e.g. .5 and integers e.g. 9 as well as negative numbers.

this is what you're looking for
$re = "~ #delimiter
^ # start of input
-? # minus, optional
[0-9]+ # at least one digit
( # begin group
\. # a dot
[0-9]+ # at least one digit
) # end of group
? # group is optional
$ # end of input
~xD";
this only accepts "123" or "123.456", not ".123" or "14e+15". If you need these forms as well, try is_numeric

Regular Expressions are for matching string patterns. If you are not explicitly after validating the input string's format (but the actual value), you can also use
filter_var("1.33", FILTER_VALIDATE_FLOAT);
to make sure the input can be used as a float value. This will return FALSE if it is not a float and the float or integer value otherwise. Any type juggling rules apply.

This regex:
\d*(?:\.\d+)?
will give results:
123 -> true
123.345 -> true
123. -> true
.345 -> true
0.3345 -> true
However, you must check emptiness of the input before using it because the regex also permit zero-length input.

You can use is_numeric() with the caveat that it accepts a bit more than one usually wants (e.g. 1e4).

I wrote the following regex that seems to work best for my test inputs so far,
/^-?(\d|[1-9]+\d*|\.\d+|0\.\d+|[1-9]+\d*\.\d+)$/
It matches integer using the first two alternatives
\d|[1-9]+\d*
Then it look for numbers like .5, .55, .05 etc., that is beginning with a .
\.\d+
Then it looks for the same as previous but a 0 before the .
0\.\d+
Then finally it looks for patterns integer and decimal parts, such as 5.5, 5.05 etc.
[1-9]+\d*\.\d+
You can test the regex in this link
Validate float - regex101

Why not use http://php.net/manual/en/function.is-float.php ? But anyhow, the RegEx would be ^[\d]+(|\.[\d]+)$ have fun!

Why not just use is_numeric if you're not experienced with regular expressions.
As to your regex: . matches all characters, \. matches a dot. {1} is not necessary. And I have no clue what you're trying to do with [^ ... ]. Read the regular expressions tutorial if you really want to use regular expressions somewhere in your code.

Related

plus-minus (±) sign in regex

I need to produce a regex pattern that verifies UTC offsets. These are typically formatted as UTC+05:30 or UTC-01:00. It seemed simple enough to match as follows (being permissive for spaces):
^UTC[ ]?[+\-±][ ]?[01][0-9]:[034][05]$
[Note: I updated this pattern based on feedback from #barman]
There is a pocket case in which the code is written UTC±00:00. However, the plus-minus sign is throwing things off. Using PHP for example:
echo preg_match("/^±$/","±");
echo preg_match("/^[±]$/","±");
echo preg_match("/^[\±]$/","±");
Will return true for the first match but false on the other two.
So my question is, does the ± require special handling in Regex? I can't find any reference to this symbol in the docs. Thx.
It looks like #Barmar probably solved the first issue you were having (matching the UTC string). However, to explain what you were seeing with:
preg_match("/^±$/","±"); // true
preg_match("/^[±]$/","±"); // false
preg_match("/^[\±]$/","±"); // false
The ± character is two bytes long, so preg_match is interpretting it as two characters. In order to match in the way you expect, you have to use the /u modifier. This tells preg_match to treat your pattern as utf-8, which will interpret ± as a single character instead of two characters.
preg_match("/^[±]$/u","±"); // true
And to include an example that matches your UTC sample:
// with the /u modifier (works as expected)
preg_match("/^UTC[ ]?[+\-±][ ]?[01][0-9]:[034][05]$/u", "UTC±05:30"); // true
// without the /u modifier (does not match)
preg_match("/^UTC[ ]?[+\-±][ ]?[01][0-9]:[034][05]$/", "UTC±05:30"); // false
You mustn't put the - between two characters inside [], that makes it create a range (like when you write [0-9]) rather than matching the - character literally.
You should put the - at the beginning or end, or escape it.
^UTC[ ]?[+\-±][ ]?[01][0-9]:[034][05]$
Also, you don't put | inside [] character sets. That's used inside () to create alternative patterns.

Combine two regular expressions for php

I have these two regular expression
^(((98)|(\+98)|(0098)|0)(9){1}[0-9]{9})+$
^(9){1}[0-9]{9}+$
How can I combine these phrases together?
valid phone :
just start with : 0098 , +98 , 98 , 09 and 9
sample :
00989151855454
+989151855454
989151855454
09151855454
9151855454
You haven't provided what passes and what doesn't, but I think this will work if I understand correctly...
/^\+?0{0,2}98?/
Live demo
^ Matches the start of the string
\+? Matches 0 or 1 plus symbols (the backslash is to escape)
0{0,2} Matches between 0 and 2 (0, 1, and 2) of the 0 character
9 Matches a literal 9
8? Matches 0 or 1 of the literal 8 characters
Looking at your second regex, it looks like you want to make the first part ((98)|(\+98)|(0098)|0) in your first regex optional. Just make it optional by putting ? after it and it will allow the numbers allowed by second regex. Change this,
^(((98)|(\+98)|(0098)|0)(9){1}[0-9]{9})+$
to,
^(?:98|\+98|0098|0)?9[0-9]{9}$
^ this makes the non-grouping pattern optional which contains various alternations you want to allow.
I've made few more corrections in the regex. Use of {1} is redundant as that's the default behavior of a character, with or without it. and you don't need to unnecessarily group regex unless you need the groups. And I've removed the outer most parenthesis and + after it as that is not needed.
Demo
This regex
^(?:98|\+98|0098|0)?9[0-9]{9}$
matches
00989151855454
+989151855454
989151855454
09151855454
9151855454
Demo: https://regex101.com/r/VFc4pK/1/
However note that you are requiring to have a 9 as first digit after the country code or 0.

Regex - matching all between second set of brackets ([])

I have the following string that I need to match only the last seven digets between [] brackets. The string looks like this
[15211Z: 2012-09-12] ([5202900])
I only need to match 5202900 in the string contained between ([]), a similar number could appear anywhere in the string so something like this won't work (\d{7})
I also tried the following regex
([[0-9]{1,7}])
but this includes the [] in the string?
If you just want the 7 digits, not the brackets, but want to make sure that the digits are surrounded with brackets:
(?<=\[)\d{7}(?=\])
FYI: This is called a positive lookahead and positive lookbehind.
Good source on the topic: http://www.regular-expressions.info/lookaround.html
Try matching \(\[(\d{7})\]\), so you match this whole regular expression, then you take group 1, the one between unescaped parentheses. You can replace {7} with a '*' for zero or more, + for 1 or more or a precise range like you already showed in your question.
You can try to use
\[(\d{1,7})\]
If first pattern looks like yours (not only digits), then this should work for you to extract group of digits surrounded by brackets like ([123]):
\(\[(\d+)\]\)
From your details, lookbehind and lookaround seems to be good one. You can also use this one:
(\d{7})\]\)$
Since the pattern of seven digit is expected at the end of the line, engine need to work less in order to find the match.
Hope it helps!
Here is a benchmark (in Perl, but I think is close the same in php) that compares lookaround approach and capture group:
use Benchmark qw(:all);
my $str = q/[15211Z: 2012-09-12] ([5202900])/;
my $count = -3;
cmpthese($count, {
'lookaround' => sub {
$str =~ /(?<=\[)\d{7}(?=\])/;
},
'capture group' => sub {
$str =~ /\[(\d{7})\]/;
},
});
result:
Rate lookaround capture group
lookaround 274914/s -- -70%
capture group 931043/s 239% --
As we can see, capture is more than 3 times faster than lookaround.

Check if a variable is a natural number

I want to make a bid system on a website. That means users can post their bid (natural number). I want to make sure users don't try to post characters, decimal numbers, etc.
I don't want to use is_numeric function because hexadecimal notation is allowed.
I was thinking to use preg_match for this. But in php.net the documentation for this function is little and I have no idea how to use preg_match.
So how should I check if a variable is a natural number with preg_match?
If you don't require decimal points: ctype_digit or filter_var($var, FILTER_VALIDATE_INT).
If you do: filter_var($var, FILTER_VALIDATE_FLOAT).
ctype_digit does what you want:
Checks if all of the characters in the provided string, text, are numerical.
(Before PHP 5.1.0, this function returned TRUE when text was an empty string.)
Either preg_match('/^[0-9]+$/', $var); or ctype_digit
I would generally caution against using regex for parsing numerics, as there are generally better solutions than regex for this, but since you're asking, I'll try to give you some assistance with it:
preg_match uses regular expressions (regex) for it's matching.
You can find out more about regex syntax at sites like http://www.regular-expressions.info/
If you want to match a digit in regex, you can either use [0-9] or \d.
If you want to match one or more of anything, you would use a plus sign.
Finally, regex strings need to be enclosed in a pair of characters. The character chosen is usually a slash (/) character, as some languages specifically require this character, but PHP also allows other characters to be used; tilde (~) is quite common.
So your regex string to match any number of digits would be "/\d+/". This can then be put into a preg_match call like so:
$isnumeric = preg_match("/\d+/",$input_string);
If you have more specific requirements, you can limit the number of characters allowed by replacing the plus sign with {max} or {min,max} where 'min' and 'max' are the number of times the preceding match is allowed. So to allow a number between two and six digits long, you would use this:
$isnumeric = preg_match("/\d{2,6}/",$input_string);
If you need to allow a decimal point, you need to know that the dot character is a special character in regex (it means 'match any character at all'), so you need to escape it with a back-slash.
Therefore, a regex to match a currency amount with two decimal places, and at least one digit before the point would be like this:
$isnumeric = preg_match("/\d+\.\d\d/",$input_string);
Finally, note that regex will return true in all the above if the string simply contains the matched value. To ensure it doesn't contain anything else, you would need to 'anchor' it to the front and end of the string, using the anchor characters: ^ for the start of the string, and $ for the end.
So for the previous example, if you want it to only contain a decimal number, and nothing else, you would need this:
$isnumeric = preg_match("/^\d+\.\d\d$/",$input_string);
Regex is a complex subject, but I hope that gives you a start.
I know this is very old but I wanted to share the next solution in case someone else comes up with this problem.
I'm assuming that by natural number you meant positive integer (which excludes the number 0).
function is_positive_integer( $value ) {
// Check if is integer and greater than zero
if( is_int( $value ) && $value > 0 ) {
return true;
}
// Is not a positive integer
else {
return false;
}
}
This kind of depends on your definition of natural numbers - according to different theories, the number zero (0) does or does not count as a natural number.
To answer your question on how to solve this with preg_match:
If you want to include zero, using preg_match is pretty easy preg_match('^[0-9]+$', $input).
Usage:
if (preg_match('^[0-9]+$', $input))
// $input represents a non-negative numeric value
else
// $input does not represent a non-negative numeric value
If you don't want to include the zero, use preg_match('^[1-9][0-9]*$', $input):
if (preg_match('^[1-9][0-9]*$', $input))
// $input represents a positive numeric value
else
// $input does not represent a positive numeric value
That said - for your particular problem, using ctype_digit is a faster solution, as others already pointed out (you'd have to do a second check if you don't want to allow the number zero).
in_array(str_replace(str_split('0123456789'), '', $s), array(',','.',''));
simple function:
function isnature($x){
$y = ceil($x)-floor($x);
return $y == 0 ? true : false;
}
From a mathematical point of view, a natural number is a positive integer, including zero, so you could check it like this:
is_int($bid) && $bid >= 0
Simplest and faster
if( is_numeric( $key ) && intval( $key ) == $key )
{
//key == number
}

What's the difference between these perl compatible regular expressions?

An answer from another question piqued my curiosity.
Consider:
$string = "asfasdfasdfasdfasdf[[sometextomatch]]asfkjasdfjaskldfj";
$regex = "/\[\[(.+?)\]\]/";
preg_match($regex, $string, $matches);
$regex = "/\[\[(.*)\]\]/";
preg_match($regex, $string, $matches);
I asked what the difference between the two regexes is. The aswer I got was that ".*" matches any character 0 or more times as many times as possible,
and ".+?" matches any character 1 or more times as few times as possible.
I read those regexes differently so I did some experimenting on my own but didn't come to any conclusions. Php.net says "?" is equivalent to {0,1} so you could rewrite
"/\[\[(.+?)\]\]/"
as
"/\[\[((.+){0,1})\]\]/"
or as
"/\[\[(.{0,})\]\]/"
or as
"/\[\[(.*)\]\]/"
Will they capture different text? Is the difference that one is less expensive? Am I being anal?
Stand-alone, ? does mean {0,1}, however, when it follows something like *, +, ?, or {3,6} (for example), ? means something else entirely, which is that it does minimal matching. So, no, you can't rewrite /\[\[(.+?)\]\]/ as /\[\[((.+){0,1})\]\]/. :-)
Just take an example where you get different results:
foo [[bar]] baz [[quux]]
Your first regular expression will match [[bar]] and [[quux]] while the second will match only [[bar]] baz [[quux]].
The reason for that is that a lazy quantifier (suffixed with ?) will match the minimum of possible repetitions the normal greedy mode will match the maximum of possible repetitions:
However, if a quantifier is followed by a question mark, then it ceases to be greedy, and instead matches the minimum number of times possible, so the pattern /\*.*?\*/ does the right thing with the C comments. The meaning of the various quantifiers is not otherwise changed, just the preferred number of matches. Do not confuse this use of question mark with its use as a quantifier in its own right. Because it has two uses, it can sometimes appear doubled, as in \d??\d which matches one digit by preference, but can match two if that is the only way the rest of the pattern matches.
Normally, ? means "capture the preceding thing 0 or 1 times". However, when used after a * or +, a ? modifies the meaning of the * or +. Normally, */+ mean "match 0 (1 for +) or more times, and match as many as possible". Adding the ? modifies that meaning to be "match 0 (1 for +) or more times, but match as few as possible". By default those expressions are "greedy", ? modifies them to be non-greedy.
The ? will only capture it one time ( the (0,1) means 0 to 1 times) where as the * will capture it as many times as it occurs in the string.
From this page:
If you take <.+> and use it on The <em>Big</em> Dog. it will give <em>Big</em>. Where as <.+?> will only match <em>
/.*/ === /.{0,}/
/.+/ === /.{1,}/
/.?/ === /.{0,1}/
"aaaaaa" =~ /a*/; # "aaaaaa"
"aaaaaa" =~ /a*?/; # ""

Categories