Search code examples
phpregexpreg-match

Matching for math equations using PHP


I'm trying to write a preg_match for math equations, but for some reason when I print_r it nothing is showing up. I'm not sure what I'm doing wrong.

$text = "22/7";
preg_match("~([0-9]+([+\-*x]|(?:plus|add|minus|subtract|divide|time|multiply)(?:es|s)?(?: by)?)(?: )?[0-9]+)(((([+\-*x]|plus|add|minus|subtract|divide|time|multiply)(?:es|s)?(?: by)?)(?: )?([0-9]+))+)?~", $text, $match);
print_r($match);

Solution

  • The Original Problem

    The problem was that there was no divide symbol present in the character group:

    [+\-*x]
    

    And should be changed to:

    [+*x/-]
    

    Enhancement

    Having a further look into your regex, I wanted to see whether I could simplify it a little bit, while also adding functionality. I came up with this:

    ^((-?\d+(?:\.\d+)?)(?:[*+/^eE-]| (?:to the power of|plus|add|minus|subtract|divided?|times|multipl(?:y|ied))(?: by)?)(?: )?)(?1)*(?2)$
    

    See the demo

    I've added:

    • floating point numbers, (1.58-0.58)
    • optional minus numbers, (2*-4)
    • to the power of, (2^8)
    • the scientific notation (9e100)
    • a recursive pattern (2^8*10-9)

    I'm glad you're using PHP - using the PCRE regex engine, you can do some pretty cool stuff.

    Breakdown:

    • (-?\d+(?:\.\d+)?) - capture an optional minus, followed by a digit, followed by an optional dot and more digits (minus and floating point additions)
    • [*+/^eE-] - any character in this group (scientific notation, to the power of addition)
    • (?:to the power of|plus|add|minus|subtract|divided?|times|multipl(?:y|ied))(?: by)? - any group in this (added "to the power of")
    • (?1)*(?2) - Recurse group 1's regex (the entire of the pattern before it) as many times as possible, then recurse group 2's regex (the digit section), to always end on a number (recursive pattern)