Link to home
Start Free TrialLog in
Avatar of steamngn
steamngn

asked on

PHP regex expression to capture and replace part of string

Say I have a string and within that string are multiple occurrences of a string similar to "@41|8:00|10/01/2015@".
What I need to do is find each of these strings and remove everything between the two "|" so "@41|8:00|10/01/2015@" needs to become "@41|10/01/2015@".
I   can find and replace the entire string with
preg_replace('/@[^>]*@/', 'replaced', $teststr);

Open in new window

but how do I find a replace only that center portion?
I just cannot get my head around the expression...
Andy
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of steamngn
steamngn

ASKER

Julian,
Right on the money! Ok, without taking up your entire day can you break this out a bit and explain it to me? I fought with this all day and you hit it out of the park first pitch<insanely jealous></insanely jealous>
Andy
excellent!
Expression Explained
/(@\d+)\|.*?\|(.*?@)/

(@\d+) - match anything that starts with a '@' followed by one or more digits (\d). The ( ) around the expression means we want to save it as a parameter so that we can use it in the replace

\| - | is a special char in regex (means or) - so we have to escape it with a '\' - we don't need it because we will recreate it in the replace.

.*? - no ( ) because we are not interested in this bit. the .* says match anything the ? says don't be greedy.
.* will match anything which would include the next \| - however we want it to stop matching when it hits the \| so we put a ? after the .* to say don't be greedy take only what you can up until the next thing we are looking for - in this case the \|
\| - the next | delimiter
(.*?@) - the ( ) says keep this for use in the replace (this will be parameter #2) - says match anything but don't be greedy (?) until you hit a @ - include that in the match and then stop.

Why do we not put a ? (don't be greedy) after the \d+ in the first match?
Answer: we could but it is not necessary. The \d specifier only matches 0-9 - so as soon as it hits a non digit it stops anyway.
What do the opening and closing '/' mean
Answer: they are just regular expression delimiters saying where it starts and where stops.

Now for the replace - easy
\1|\2
\1 means the first saved match - (@\d+)
| - insert a | - we don't need to escape it because in the replace string the | character is just a |
\2 - the second matched parameter (.*?@)
You are welcome.
Julian,
I went round and round ALL DAY on this.... and now with your insight I see where I was going wrong!
Excellent help, Thank you
Andy
Again you are welcome Andy - glad I could be of assistence.