Parse a String with PHP’s preg_match_all()

Several times I’ve run into scenarios where I needed to essentially parse a string in PHP that wasn’t in a common format (JSON, CSV, tab-separated, etc.). Early on in my career I avoided regular expressions (RegEx) like the plague but a few years back I decided the time was right to embrace RegEx. Good thing I did, too, because with PHP’s preg_match_all() function, solving this requirement was a breeze

My scenario was, I’ve got the following string: Package #1 Box name: Medium Box : 6x4x3: W=1.4: Value=199.99: SKU=1 *  Mobile Phone 1.4lb; Package #2 Box name: Large Box : 10x7x5: W=0.7: Value=39.99: SKU=1 *  Phone Case 2.1lb;. This string is related to an order on an ecommerce store and it tells me that the best way to ship this order is in two separate boxes, once called “Medium Box” and the other called “Large Box.”

This string is not in an easy-to-parse format but it is consistent! What I needed to do was get everything between every occurrence of “Box Name: ” and the subsequent ” : “. Initially I considered using PHP’s substr() function in conjunction with strpos(). I’d use strpos() to work out where “Box Name: ” was, use strpos() again with an offset to look for the subsequent ” : “, adjust both those numbers, and feed that back into substr() as the start and end. What a pain. And, when I have a string that contains multiple boxes as my example does, I’m forced to loop and keep iterating up the offset. That could work, but not really a good solution.

Enter preg_match_all()! Three lines of code is all it took to prove it worked:


$comment = “Package #1 Box name: Medium Box : 6x4x3: W=1.4: Value=: SKU=1 * Samsung Mobile Phone 1.4lbs 1.4lb; Package #2 Box name: Large Box : 10x7x5: W=1.4: Value=: SKU=1 * Samsung Mobile Phone 1.4lbs 1.4lb;”;

preg_match_all(“/Box name: (.*?) : /”, $comment, $boxNames);

print_r($boxNames[1]);

The result from the print_r() on the last row there is: Array ( [0] => Medium Box [1] => Large Box ). That’s exactly what I needed. I could, of course, use additional preg_match_all()’s to find other elements like the box dimensions, weight, etc.

preg_match_all() takes three parameters in this scenario: a regular expression that covers the start element to look for (“Box Name: “) as well as the end element to look for (” : “); a string, and an output variable. Note that this line isn’t written as $boxNames = preg_match_all(…);, instead $boxNames is the third parameter.

$boxNames becomes an array of values. The first element of that array ($boxNames[0]) is the full match (in this case $boxNames[0][0] = “Box Name: Medium Box : “ and $boxNames[0][1] = “Box Name: Large Box : “). The second element of the array ($boxNames[1]) is the internal strings ($boxNames[1][0] = “Medium Box” and $boxNames[1][1] = “Large Box”). That’s the one I wanted so that’s the one I used. The array will contain as many matches as preg_match_all() finds (hence the “_all”).

Note

A tool like RegExr is useful here when putting together your expression. I’ve covered this in more detail previously.

Leave a Reply