Problems with preg_match - php

I'm using preg_match as a way to validate inputs on a form. Specifically, I am trying to validate input of currency. Here is the function:
if (preg_match("/^\$(((\d{1,3},)+\d{3})|\d+)\.\d{2}$/i", $inString)) {
return True;
} else {
return False;
}
I can get this to work AT ALL. I keeps returning False regardless of what I feed it (including valid strings). I'm sure I'm doing something obviously wrong, but I can't see it. You know how it is...
Anyone have any suggestions?

Try something like this:
$inString = '1550.50';
if (preg_match("/\b\d{1,3}(?:,?\d{3})*(?:\.\d{2})?\b/", $inString)) {
echo "True";
} else {
echo "False";
}
explanation:
\b # word boundary assertion
\d{1,3} # 1-3 digits
(?: # followed by this group...
,? # an optional comma
\d{3} # exactly three digits
)* # ...any number of times
(?: # followed by this group...
\. # a literal dot
\d{2} # exactly two digits
)? # ...zero or one times
\b # word boundary assertion

The preg_match function already returns True or False depending on whether it matches, so there is no need to return True or False a second time.
This means you can directly echo the values of True or False:
$inString = "$12.50";
$price_regex = '~^\$(((\d{1,3},)+\d{3})|\d+)\.\d{2}$~';
echo preg_match($price_regex, $inString);
// echoes 1
You can also directly return these values:
return preg_match($price_regex, $inString);
You can perform a Boolean test:
if( preg_match($price_regex, $inString) ) { // take some action }
else { // take another action }
If what you want instead is to echo some value depending on whether there is a match, do this:
echo (preg_match($price_regex, $inString)) ? "**It Matches!**" : "Nah... No match." ;
Notes:
Changed the delimiter to ~ (more legible)
Removed the i flag (there are no letters, so it doesn't need to be case-insensitive)

Both answers given before this work, but here's an explanation of why the original preg_match pattern didn't work.
It's because the pattern is enclosed in double quotes. When PHP sees this, it treats whatever follows a $ sign as a variable name. If you need to include a literal $ sign inside a double quoted string, the dollar has to be preceded by a backslash.
so both of these patterns work:
'/^\$(((\d{1,3},)+\d{3})|\d+)\.\d{2}$/i'
"/^\\$(((\d{1,3},)+\d{3})|\d+)\.\d{2}\$/i"
Obviously, using single quotes is simpler in this case.

Related

How to validate letter & number or only letter strings?

I want to match letters and numbers, but not only numbers.
So I want to create a preg_match() pattern to filter like this:
eg:
no123 true
123no true
123456 false
letters true
So we must have at least one letter. There can be any amount of digits before it and any amount of alphanumeric characters is allowed until end of the string.
/^\d*[a-z][a-z\d]*$/i
^ start of string
\d* any amount of digits
[a-z] one letter
[a-z\d]* any amount of alphanumeric characters
$ until end of the string
i flag for caseless matching
See this demo at regex101
Using a SKIP-FAIL pattern will outperform Toto's pattern (and MH2K9's answer is incorrect as it doesn't allow all alphabetical matches). You can test their patterns on the sample text in my demo link.
/^\d+$(*SKIP)(*FAIL)|^[a-z\d]+$/i
Pattern Demo Link
This "disqualifies" purely numeric strings, and matches mixed (numeric-alphabetical) and purely alphabetical strings.
Code: (Demo)
$string='test123';
var_export(preg_match('/^\d+$(*SKIP)(*FAIL)|^[a-z\d]+$/i',$string)?true:false);
Output:
true
UPDATE: Regular expressions aside, this task logic can be performed by two very simple non-regex calls: ctype_alnum() and ctype_digit()
Code: (Demo)
$tests = [
'no123', // true
'123no', // true
'123456', // false
'letters', // true
];
foreach ($tests as $test) {
echo "$test evaluates as " , (ctype_alnum($test) && !ctype_digit($test) ? 'true' : 'false') , "\n";
}
Output:
no123 evaluates as true
123no evaluates as true
123456 evaluates as false
letters evaluates as true
You can try this Regex. It checks both number and letter at least one.
(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)$
According to your comment: "only letters vaild but only number invalid.", this wil do the job:
if (preg_match('/^(?=.*[a-z])[a-z0-9]+$/i', $inputString)) {
// valid
} else {
// invalid
}
Explanation:
/ : regex delimiter
^ : start of string
(?=.*[a-z]) : lookahead, make sure we have at least one letter
[a-z0-9]+ : string contains only letters and numbers
$ : end of string
/i : regex delimiter + flag case insensitive

Compare username to regular expression with PHP

I've never used regular expressions before and did some research on how to allow my username field only alphanumeric characters, dashes, dots, and underscores. I have the following expression but it doesn't seem to be working.
$string = "Joe_Scotto";
if (!preg_match('[a-zA-Z0-9_-.]', $string)) {
echo "Does not match Regex";
} else {
echo "Matches";
}
I want the statement to return true if it is following the "guidelines" and false if the username contains something other than what I specified it should contain. Any help would be great. Thanks!
Try this
$string = "Joe_Scotto";
if (!preg_match('/^[A-Za-z0-9_.]+$/', $string)) {
echo "Does not match Regex";
} else {
echo "Matches";
}
You match only a single character. Try this:
$string = "Joe_Scotto";
if (!preg_match('/^[a-zA-Z0-9_.-]+$/', $string)) {
echo "Does not match Regex";
} else {
echo "Matches";
}
The + sign says: match 1 or more characters defined directly before the + (* is the same but matches 0 or more characters).
Also the separators '/' (or any other separator characters) are required.
And in character classes, it is better to place the - sign to the end, else it could be misinterpreted as range from _ to .
And add ^ at the beginning (this means: match from the beginning of the input) and $ to the end (this means: match to the end of the input). Else, also a part of the string would match.
You should use something like that http://www.phpliveregex.com/p/ern
$string = 'John_Buss';
if (preg_match('/[A-z0-9_\-.]+/', $string)) {
return true;
} else {
return false;
}
Make sure to add / delimiter character at the start and the end of your regex
Make sure to use \ escape character before -
Make sure to add + character quantifier

I need a RegExp to only match Latin characters and not else

I have written the following code to check if the given string is Latin or it contains some other non-latin chars like Persian. The issue is that it always returns true for both of the following strings:
$str = "Hello, What's up?"
Or
$str = "Hello, سلام"
While for the second string it should return false since it contains Persian characters (non-latin) too.
$default_rule = "/[a-zA-Z0-9\(\)\*_\-\!\#\$\%\^\&\*\,\.\"\'\]\[]*/";
$rule = ($rule==null) ? $default_rule : $rule;
if(preg_match($rule, $str)==true)
{
// always returns true
}
Your pattern will return true if the string contains zero or more of those characters you've specified. In other words, it will return true for any string at all. You need to put start (^) and end ($) anchors around it. Also you don't need to escape most of those characters (the character class causes them to be treated as literal characters):
$default_rule = '/^[a-zA-Z0-9()*_\-!#$%^&*,."\'\][]*$/';
But, this will match an empty string. To also make sure that the string is not empty, use the + quantifier (one or more) instead of *.
$default_rule = '/^[a-zA-Z0-9()*_\-!#$%^&*,."\'\][]+$/';

Regex: match two adjacent strings

I have some code such as:
if('hello' == 2 && 'world' !== -1){
return true;
}
I'm having some trouble matching the condition in the if statement. The first regex I thought of was /'.*'/, but this matches:
'hello'
' == 2 && '
'world'
which isn't what I was hoping for. I only want to match the single quotes and the text inside.
'hello'
'world'
Any body have any idea?
Try this
preg_match_all('/\'[^\'\r\n]*\'/m', $subject, $result, PREG_PATTERN_ORDER);
for ($i = 0; $i < count($result[0]); $i++) {
# Matched text = $result[0][$i];
}
Explanation
"
' # Match the character “'” literally
[^'\\r\\n] # Match a single character NOT present in the list below
# The character “'”
# A carriage return character
# A line feed character
* # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
' # Match the character “'” literally
"
The two matching groups int this should pick up your quoted values:
^.*(\'.*?\').*(\'.*?\').*$
For your specific case
\'[a-z]*?\'
For the entire code, if you have uppercase characters in the quotes, you can use
\'[a-zA-Z]*?\'
However, if you have special characters in the quotes as well, then you can use what #Chris Cooper suggested. Depending on your need, there are a variety of answers possible.
Note: '?' after * makes * non-greedy, so it wont try to search till the last quote.
It also matters which regex method you use to get the answers.
Here's what I came up with!
preg_match_all("#'[^'\n\r]*'#", $subject, $matches);
Match '.
Match any character that is not ', new line, or carriage return.
Match '.
Without all of the escaping, I think it's a bit more readable—for being a regular expression, anyway.

PHP regular expression for numbers and commas only

I need to create a regular expression to validate comma separated numeric values.
They should look like: 1,2,3,4,5 etc....
The value must be either a single digit like: 1 no empty spaces before or after, no commas before or after.
Or... multiple numerical values separated by commas. First and last characters must be a number.
I have the following code but it only checks for numbers and commas in no particular order:
How can I change the regular expression below to fit the above description?
Thank you!
// get posted value
if(isset($_POST['posted_value']))
{
$sent_value = mysqli_real_escape_string($conn, trim($_POST['posted_value']));
if(preg_match('/^[0-9,]+$/', $posted_value))
{
$what_i_need = $posted_value;
}
else
{
$msg .= $not_what_i_need;
}
}
else
{
$msg .= $posted_value_not_set;
}
This should do it:
/^\d(?:,\d)*$/
Explanation:
/ # delimiter
^ # match the beginning of the string
\d # match a digit
(?: # open a non-capturing group
, # match a comma
\d # match a digit
) # close the group
* # match the previous group zero or more times
$ # match the end of the string
/ # delimiter
If you allow multi-digit numbers, then change \d to \d+.
Do you allow the user to input numbers with commas in them, like 5,000 for example? what about decimals like 5.6?
Alternatively you could validate the input using explode something like this.
$values = explode(',',$sent_value);
$valid = true;
foreach($values as $value) {
if(!ctype_digit($value)) {
$valid = false;
break;
}
}

Categories