Denis Matafonov
Denis Matafonov

Reputation: 2812

Shortest way to get matched patterns from a string with regex

I have pretty long string to parse, that looks like that (part of it)

$string = 'FIRM_ID = MC0356400000; TAG = EQTV; CURR_CODE = SUR; CLIENT_CODE = FR334; LIMIT_KIND = 1; OPEN_BALANCE = 4822.84; OPEN_LIMIT = 0.00; LEVERAGE = 0;'

I need to get values for php variables from that string, which I do with preg_match:

 preg_match("/FIRM_ID = (.*?);/", $string, $m);
 $firm_id = trim($m[1]);

 preg_match("/CLIENT_CODE = (.*?);/", $string, $m);
 $client_code = trim($m[1]);

... and so on

I was wondering is there a way to do the same in one line? May be with preg_replace or other functions, so I would not have to declare $m variable first and then take out from that [1] element.

So the code supposed to look like

 $firm_id = somefunction($string);
 $client_code = somefunction($string);

Its not practical question, more theoretical. I know how to get result that I need, I want to know if there is a simpler and more elegant way.

Thanks.

Upvotes: 1

Views: 65

Answers (3)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627341

Match and capture key-value pairs and then combine into an array:

$re = '/(\w+)\s*=\s*([^;]*)/';
$str = 'FIRM_ID = MC0356400000; TAG = EQTV; CURR_CODE = SUR; CLIENT_CODE = FR334; LIMIT_KIND = 1; OPEN_BALANCE = 4822.84; OPEN_LIMIT = 0.00; LEVERAGE = 0;';
preg_match_all($re, $str, $matches);
print_r(array_combine($matches[1],$matches[2]));

See the PHP demo, result:

Array
(
    [FIRM_ID] => MC0356400000
    [TAG] => EQTV
    [CURR_CODE] => SUR
    [CLIENT_CODE] => FR334
    [LIMIT_KIND] => 1
    [OPEN_BALANCE] => 4822.84
    [OPEN_LIMIT] => 0.00
    [LEVERAGE] => 0
)

The regex is

/(\w+)\s*=\s*([^;]*)/

See is demo online.

Details:

  • (\w+) - Group 1: one or more word chars
  • \s*=\s* - a = enclosed with optional whitespace(s)
  • ([^;]*) - Group 2: zero or more chars other than ;.

To "initialize" the variables each at a time, you may use a

$var_name = 'FIRM_ID';
$re = '/' . $var_name . '\s*=\s*\K[^;]*/';
$str = 'FIRM_ID = MC0356400000; TAG = EQTV; CURR_CODE = SUR; CLIENT_CODE = FR334; LIMIT_KIND = 1; OPEN_BALANCE = 4822.84; OPEN_LIMIT = 0.00; LEVERAGE = 0;';
preg_match($re, $str, $m);
print_r($m);

See the PHP demo.

The \K is the match reset operator that omits all text matched so far within the current match iteration.

Upvotes: 2

anubhava
anubhava

Reputation: 785971

You can also use list function after preg_match_all :

preg_match_all('/(\w[\w-]*)\h*=\h*([^;\h]+);/', $string, $matches);

list($firmId, $tag, $currCode, $clientCode, $limitKind, $openBalance, $openLimit, $leverage) = $matches[2];

echo $firmId;
//=> MC0356400000
echo $tag;
//=> EQTV
echo $clientCode;
//=> FR334
echo $openBalance;
//=> 4822.84

Upvotes: 1

AbraCadaver
AbraCadaver

Reputation: 79014

If you remove spaces and replace ; with &, you can do this:

parse_str(str_replace([' ', ';'], ['', '&'], $string), $result);

Which yields an easy to use associative array:

Array
(
    [FIRM_ID] => MC0356400000
    [TAG] => EQTV
    [CURR_CODE] => SUR
    [CLIENT_CODE] => FR334
    [LIMIT_KIND] => 1
    [OPEN_BALANCE] => 4822.84
    [OPEN_LIMIT] => 0.00
    [LEVERAGE] => 0
)

So just echo $result['FIRM_ID'];

Upvotes: 3

Related Questions