16

How can I replace a substring in a found pattern, but leaving the rest as it is?

(EDIT: The real case is of course more complicated than the example below, I have to match occurrences within xml tags. That's why I have to use regex!)

Let's say I want to change occurrences of the letter "X" within a word to the letter "Z".

I want

aaXaa aaX Xaa

to become

aaZaa aaZ Zaa

Finding occurrences of words including "x" isn't a problem, like this:

[^X\s]X[^\s]

but a normal preg_match replaces the complete match, where I want anything in the pattern except "X" to stay as it is.

Which is the best way to accomplish this in php?

3
  • Your regex would not match the X at the end of the second word. Commented Jan 24, 2010 at 11:37
  • I'm confused, doesn't a simple replace do exactly what you ask? Replacing the matching pattern and leaving the rest as is. Commented Jan 24, 2010 at 11:45
  • Sorry for cunfusing. I have to user regex, my example was a bit over-simplified! Commented Jan 24, 2010 at 11:56

5 Answers 5

15

If your regex matches only the relevant part, it should be no problem that it replaces the complete match (like preg_replace('/X/', 'Z', $string)).

But if you need the regex to contain parts that should not be replaced, you need to capture them and insert them back:

preg_replace('/(non-replace)X(restofregex)/', '$1Z$2', $string);
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, Soulmerge! Exactly what I needed!
I found when concatenating a string variable between the two matching groups I had to put the numbers in curly brackets, like this '${1}' . $foo . '${2}', otherwise it didn't work. Why is that?
If instead of Z you need to put value from a variable that you do not control, then you need to escape the $ and \number characters, and this is quite a difficult task. Use preg_replace_callback, an example is in my answer to the question.
3

If it's really as simple as replacing X with Z, you can also use str_replace(), which is faster than using preg in this case:

$sNew = str_replace("X", "Z", $sOld);

1 Comment

I get your point, and the real case is of course more complicated. I will use it for handling namespace tags in xml-documents, so there has to be real regex for this!
1

Try this

<?php
$string = 'The quick brown fox jumped over the lazy dog.';
$patterns[0] = '/quick/';
$patterns[1] = '/brown/';
$patterns[2] = '/fox/';
$replacements[2] = 'bear';
$replacements[1] = 'black';
$replacements[0] = 'slow';
echo preg_replace($patterns, $replacements, $string);
?>

The above example will output:

The bear black slow jumped over the lazy dog.

1 Comment

You need to ksort the arrays before you call preg_replace, so that the right patterns get substituted by the right values: ksort($patterns); ksort($replacements);
0

Do you really have to use regex for this?

$output = str_replace('X', 'Z', $input);

Comments

0

For difficult regular expressions where you need to replace part of a string, it can be very useful to do so (and most importantly, you don't need to escape $newValue for the characters $ and \number):

$newValue = 'NewValue';

$newString = preg_replace_callback(
  '/(<Element>).*(<\/Element>)/',
  function($match) use ($newValue) { return $match[1].$newValue.$match[2]; },
  $string
);

Unreliable usage:

In preg_replace('/(<Element>).*(<\/Element>)/', '$1NewValue$2', $string): if instead of NewValue you need to put value from a variable that you do not control, then you need to escape the $ and \number characters, and this is quite a difficult task.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.