0

In the following string $str I need to explode/split the data get the part 'abc' and the first occurrence of '::' and then implode it all back together to a single string. Can the explode be done in one step instead of two consecutive explodes?

Example strings to work with:

$str="12345:hello abcdef123:test,demo::example::12345";

and the desired substring

$substr = "abcdef123:test,demo::"
bikey77
  • 6,384
  • 20
  • 60
  • 86
  • Exploding with 2 delimiters could be done with `preg_split()`: `$sub = preg_split(',|:', $str);`, but the desired output doesn't make sense to me. Can you explain the logic behind it ? – HamZa Apr 30 '13 at 18:01
  • The data is a complex array from a Wordpress db. I need to extract a part of it, edit the data and update the db with the new data. The only way I can think of doing it is to split the string, edit the "middle" part and implode it back together. – bikey77 Apr 30 '13 at 18:12
  • So the delimiters are `:` and you want to "stop" by `::` and get `xxx:yyy::` value ? – HamZa Apr 30 '13 at 18:15

2 Answers2

1

You can do it like this:

preg_match('~\s\Kabc\S+?::~', $str , $match);
$result = $match[0];

or in a more explicit way

preg_match('~\s\Kabc\w*+:\w++(?>,\w++)*+::~', $str , $match);
$result = $match[0];

explanation:

first pattern:

~ : delimiter of the pattern
\s : any space or tab or newline (something blank)
\K : forget all that you have matched before
abc : your prefix
\S+? : all chars that are not in \s one or more time (+) without greed (?) 
     : (must not eat the :: after)
~ : ending delimiter

second pattern:

begin like the first
\w*+ : any chars in [a-zA-Z0-9] zero or more time with greed (*) and the 
     : RE engine don't backtrack when fail (+) 
     : (make the previous quantifier * "possessive")
":"  : like in the string
\w++ : same as previous but one or more time
(?> )*+ : atomic non capturing group (no backtrack inside) zero or more time 
     : with greed and possessive *+ (no backtrack)
"::" : like in the string
~    : ending delimiter 
Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125
  • I'm terrible when it comes to regular expressions. This is what I'm getting: `Warning: preg_match() [function.preg-match]: No ending delimiter '~' found` – bikey77 Apr 30 '13 at 18:18
  • @bikey77: i have forgotten the ending ~. Oops – Casimir et Hippolyte Apr 30 '13 at 18:19
  • Thanks, it works for the example where the delimiter is ::, doesnt work with }} which I will also need. Can you please tell me how to change the regex accordingly? – bikey77 Apr 30 '13 at 18:26
  • @bikey77: replace :: with \}\} cause curly braces are special characters in a regex pattern – Casimir et Hippolyte Apr 30 '13 at 18:29
  • Maybe, instead, you could explain the regular expression you have written and I can do the testing? That would be easier and better for both. – bikey77 Apr 30 '13 at 18:29
0

There is probably a better way, but since I avoid regular expression like bad tennis player avoids their backhand...

<?php
list($trash,$keep)=explode('abc',$str);
$keep='abc'.$keep;
list($substring,$trash)=explode('::',$keep);
$substring.='::'; //only if you want to force the double colon on the end.
?>
TecBrat
  • 3,643
  • 3
  • 28
  • 45
  • I've edited my example string to make it clear that there wont always be a :: before abc. – bikey77 Apr 30 '13 at 18:06
  • Will it always start with "abc"? – TecBrat Apr 30 '13 at 18:14
  • I edited my answer, but in the meantime, Casimir might have solved it the 'right' way. You might want some testing in there to make sure the double colon did actually exist. – TecBrat Apr 30 '13 at 18:26