Replace Only First Match Using Preg_Replace

Replace only first match using preg_replace

The optional fourth parameter of preg_replace is limit:

preg_replace($search, $replace, $subject, 1);

Using preg_replace to replace only first match

preg_replace()'s does a Regular Expression match and replace. You are passing it a string instead of a valid RegEx as the first argument.

Instead you might be looking for str_replace() which does string replacement.

Replace first match using preg_replace

In between with regex can be a bit difficult. I recommend using the quantifer \d+ to specify you're looking specifically for a digit character, and use preg_match to fetch the first result:

<?php
function getFirstGB($str){

if (preg_match("/(\d+)GB/", $str, $matches)) {
return $matches[1];
} else {
return false;
}

}

$str = 'NGM YOU COLOR P550 DUAL SIM 5.5" IPS HD CURVO QUAD CORE 8GB RAM 1GB 4G LTE';

echo getFirstGB($str);

PHP Playground here.

Preg_replace only replaces first match

If you want to clear all br-s inside only one div-block you need to first catch the content inside your div-block and then clear all your br-s.

Your regexp has the only one <br /> in it and so it replaces only one <br />.

You need something like that:

function clear_br($a)
{
return str_replace("<br />", "", $a[0]);
}

$TEXT = preg_replace_callback("/<div class='quote'>.*?<br \/>.*?<\/div>/is", "clear_br", $TEXT);

PHP: preg_replace only first matching string in array

You may use plain text in the associative array keys that you will use to create dynamic regex patterns from, and use preg_replace_callback to replace the found values with the replacements in one go.

$internal_message = 'Hey, this is awesome!';

$words = array(
'wesome' => 'wful',
'wful' => 'wesome',
'this' => 'that',
'that' => 'this'
);
$rx = '~(?:' . implode("|", array_keys($words)) . ')\b~';
echo "$rx\n";
$message = preg_replace_callback($rx, function($m) use ($words) {
return isset($words[$m[0]]) ? $words[$m[0]] : $m[0];
}, $internal_message);
echo $message;
// => Hey, that is awful!

See the PHP demo.

The regex is

~(?:wesome|wful|this|that)\b~

The (?:wesome|wful|this|that) is a non-capturing group that matches any of the values inside, and \b is a word boundary, a non-consuming pattern that ensures there is no letter, digit or _ after the suffix.

The preg_replace_callback parses the string once, and when a match occurs, it is passed to the anonymous function (function($m)) together with the $words array (use ($words)) and if the $words array contains the found key (isset($words[$m[0]])) the corresponding value is returned ($words[$m[0]]) or the found match is returned otherwise ($m[0]).

php preg_replace or expression replace all but first match

I think you can solve this by using preg_replace_callback and keeping track of keywords you found. I've also added the grouping the @Wiktor Stribiżew suggested, and I personally like to use named-captures in RegEx.

See the comments for additional details

$string = 'gamer thing gamer games test games';
$pattern = '/\b(?<keyword>gamer|games)\b/';

// We'll append to this array after we use a given keyword
$usedKeywords = [];
$finalString = preg_replace_callback(
$pattern,

// Remember to capture the array by-ref
static function (array $matches) use (&$usedKeywords) {
$thisKeyword = $matches['keyword'];
if (in_array($thisKeyword, $usedKeywords, true)) {
return $thisKeyword;
}

$usedKeywords[] = $thisKeyword;

// Do your replacement here
return '~'.$thisKeyword.'~';

},
$string
);

print_r($finalString);

The output is:

~gamer~ thing gamer ~games~ test games

Demo here: https://3v4l.org/j40Oq

How can I make preg_replace only replace the first of *each* character matched?

If you just want a letter to be replaced only once then following regex should work:

echo preg_replace('/([aeiou])(?!.+?\\1)/', '<i>$1</i>', 'alphabet');

OUTPUT:

alph<i>a</i>b<i>e</i>t

PS: Note that it replaces last occurrence of a letter instead of the first one.

EDIT:

Following would produce the same output as expected by the OP (thanks to @AntonyHatchkins):

echo strrev(preg_replace
('/([aeiou])(?!.+?\\1)/', strrev('<i>1$</i>'), strrev('alphabet')))."\n";

EDIT 2:

Upon OP's comment:

Can you help me allow more than one a then? How can I match 2, but not 3 a's

I am posting this answer:

echo strrev(preg_replace('/([aeiou])(?!(.+?\\1){2})/', 
strrev('<i>1$</i>'), strrev('alphabetax'))) . "\n";

EDIT 3:

Upon another of OP's comment:

that will allow duplicates for all characters in the string, not just 2 a's & 1 e

I am posting this answer:

echo strrev(preg_replace(array('/(a)(?!(.+?\\1){2})/', 
'/(?<!>)([eiou])(?!.+?\\1)/'),
array(strrev('<i>1$</i>'), strrev('<i>1$</i>')), strrev('alphabetaxen')))."\n";

OUTPUT:

<i>a</i>lph<i>a</i>b<i>e</i>taxen

Note: I believe original problem has already changed so many times so please don't add further complexity in this problem. You're free to post another question if you have different queries.

preg_replace on the actual match ( index 1) instead of whole string

I don't know what you want to match with .*. You don't need it. This will work fine:

preg_replace('/(lets go)/', "going", "lets go somewhere");

Or you can use a lazy match:

preg_replace('/(lets go).*?/', "going", "lets go somewhere");

Explanation: Your original expression was greedy. That roughly means that .* matches as many characters as possible. .*? is lazy; it matches the minimum amount of characters.

You can also match 'somewhere' as a sub-pattern, and us it in the replacement:

preg_replace('/(lets go)(.*)/', "going\$2", "lets go somewhere");

Here. $0 is "lets go somewhere", $1 is "lets go", $2 is " somewhere". The backslash is needed because "going\$2" is inside double quotes.



Related Topics



Leave a reply



Submit