Josh Fleshman
Josh Fleshman

Reputation: 13

Problems with preg_match

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?

Upvotes: 1

Views: 106

Answers (3)

yitwail
yitwail

Reputation: 2009

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.

Upvotes: 1

zx81
zx81

Reputation: 41848

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)

Upvotes: 1

SpencerX
SpencerX

Reputation: 5733

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

Upvotes: 1

Related Questions