1

I am trying to extract the FQDN and port number from a standard Oracle connection string. I have figured out how to extract the FQDN and PORT individually, but I am looking for a single php regexp, which will allow me to extract all FQDN and PORT at the same time.

Sample Connection String:

(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN1)(PORT=1234))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN2)(PORT=5678))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN3)(PORT=9012))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN4)(PORT=3456)))(CONNECT_DATA=(SERVICE_NAME=STUFF)))

My expected result would be an array:

[0][0] => FQDN1, [0][1] => 1234, 
[1][0] => FQDN2, [1][1] => 5678, 
[2][0] => FQDN3, [2][1] => 9012, 
[3][0] => FQDN4, [3][1] => 3456

Any help from you guys will be appreciated.

Thanks.

Legio X
  • 111
  • 1
  • 1
  • 5

3 Answers3

2

You can use preg_match_all like this:

if (preg_match_all('~HOST=([^)\s]+).*?PORT=([^)\s]+)~', $str, $arr))
   print_r($arr);

Live Demo: http://ideone.com/btmeao

anubhava
  • 761,203
  • 64
  • 569
  • 643
  • This is what I needed, though I do not understand why the 0th index of the array has the entire HOST=...)(PORT=... and my data is located in index position 1 and 2. I would have thought that my data would be located starting at index 0. – Legio X Apr 19 '13 at 04:15
  • Nonetheless, this gets me what I need. – Legio X Apr 19 '13 at 04:15
  • @LegioX: As per PHP manual of preg_match_all: `Orders results so that $matches[0] is an array of full pattern matches, $matches[1] is an array of strings matched by the first parenthesized subpattern, and so on.` See here: http://php.net/manual/en/function.preg-match-all.php – anubhava Apr 19 '13 at 04:30
0
$str="(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN1)(PORT=1234))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN2)(PORT=5678))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN3)(PORT=9012))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN4)(PORT=3456)))(CONNECT_DATA=(SERVICE_NAME=STUFF)))";
preg_match_all('/\(HOST=(FQDN\d)\)\(PORT=(\d+)\)/', $str, $matches, PREG_SET_ORDER);
foreach($matches as $k=>$match)
    array_shift($matches[$k]);

Use PREG_SET_ORDER to arrange them the way you want them. Then array_shift to knock off the full match.

http://ideone.com/yN07yP

Whenever possible, you should read the documentation:

http://php.net/manual/en/function.preg-match-all.php

FrankieTheKneeMan
  • 6,645
  • 2
  • 26
  • 37
  • The pattern is actually rendering blanks. I had read about the preg_match_all function, but I overlooked the PREG_SET_ORDER flag. Thank you very much for providing a possible solution. I appreciate all the help. I spent a whole day tinkering with my regex, but couldn't get it to work correctly. – Legio X Apr 19 '13 at 04:26
0

Try this:

$subject = <<<LOD
(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN1)(PORT=1234))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN2)(PORT=5678))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN3)(PORT=9012))(ADDRESS=(PROTOCOL=TCP)(HOST=FQDN4)(PORT=3456)))(CONNECT_DATA=(SERVICE_NAME=STUFF)))
LOD;

$pattern = '~\(HOST=([^)]+)\)\(PORT=(\d+)\)~';

preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);

// removes the whole match (index 0) for each result to only let the capture groups
foreach ($matches as &$match) {
    array_shift($match);
}
Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125
  • I wish I could give check marks to all the right answers, but I'm only allowed one check mark. Your pattern also provides the necessary information. The PREG_SET_ORDER which I overlooked while reading on preg_match_all was icing on the cake. Thank you. – Legio X Apr 19 '13 at 04:23