You may match the specific parts of the input string using a single pattern with capturing groups:
preg_match('~^(?<code>\S+)\s+(?<name>.*?)\s+(?<num>\$\d[\d.]*)\s*(?<details>.*)$~', $text, $matches)
See the regex demo. Actually, the last $
is not required, it is there just to show the whole string is matched.
Details
^
- start of a string
(?<code>\S+)
- Group "code": one or more non-whitespace chars
\s+
- 1+ whitespaces
(?<name>.*?)
- Group "name": any 0+ chars other than line break chars, as few as possible
\s+
- 1+ whitespaces
(?<num>\$\d[\d.]*)
- Group "num": a $
, then 1 digit and then 0+ digits or .
\s*
- 0+ whitespaces
(?<details>.*)
- Group "details": any 0+ chars other than line break chars, as many as possible
$
- end of string.
PHP code:
$re = '~^(?<code>\S+)\s+(?<name>.*?)\s+(?<num>\$\d[\d.]*)\s*(?<details>.*)$~';
$str = 'BK0001 My book (4th Edition) $49.95 (Clearance Price!)';
if (preg_match($re, $str, $m)) {
echo "Code: " . $m["code"] . "\nName: " . $m["name"] . "\nPrice: " .
$m["num"] . "\nDetails: " . $m["details"];
}
Output:
Code: BK0001
Name: My book (4th Edition)
Price: $49.95
Details: (Clearance Price!)
\S+)\s+(?.*?)\s+(\$\d[\d.]*)\s*(?.*)$~', $text, $matches)`, see [demo](https://regex101.com/r/EF0I6W/1).
– Wiktor Stribiżew Nov 07 '18 at 20:43