Laravel Live Denmark 2026

preg_replace_callback

(PHP 4 >= 4.0.5, PHP 5, PHP 7, PHP 8)

preg_replace_callbackRechercher et remplacer par expression rationnelle standard en utilisant une fonction de callback

Description

preg_replace_callback(
    string|array $pattern,
    callable $callback,
    string|array $subject,
    int $limit = -1,
    int &$count = null,
    int $flags = 0
): string|array|null

Le comportement de preg_replace_callback() est presque identique à celui de preg_replace(), hormis le fait qu'à la place du paramètre replacement, il faut spécifier une fonction de rappel callback qui sera appelée, avec les éléments trouvés en arguments.

Liste de paramètres

pattern

Le masque à chercher. Il peut être une chaîne de caractères ou un tableau contenant des chaînes.

callback

La fonction de rappel qui recevra le tableau d'éléments trouvés dans la chaîne subject. La fonction de rappel doit retourner la chaîne de remplacement. Voici la signature de la fonction de rappel :

handler(array $matches): string

Vous aurez souvent besoin de la fonction callback avec preg_replace_callback() à un seul endroit. Dans ce cas, vous pouvez simplement utiliser une fonction anonyme pour déclarer une fonction de rappel pour la fonction preg_replace_callback(). En faisant cela, vous concentrez toutes les routines liées à votre remplacement à un seul endroit, et vous ne polluez pas votre espace de noms de fonctions avec des fonctions à usage unique.

Exemple #1 preg_replace_callback() et fonction anonyme

<?php
// Un filtre de ligne de commande Unix pour convertir la première lettre
// des paragraphes (commençant par "<p>") en minuscule

$fp = fopen("php://stdin", "r") or die("Impossible de lire la ligne de commande");
while (!
feof($fp)) {
$line = fgets($fp);
$line = preg_replace_callback(
'|<p>\s*\w|',
function (
$matches) {
return
strtolower($matches[0]);
},
$line
);
echo
$line;
}
fclose($fp);
?>

subject

La chaîne ou le tableau de chaînes à chercher et à remplacer.

limit

Le nombre maximal de remplacement pour chaque masque dans chaque chaîne subject. Vaut par défaut -1 (aucune limite).

count

Si fournie, cette variable sera remplie avec le nombre de remplacements effectués.

flags

flags peut être une combinaison des drapeaux PREG_OFFSET_CAPTURE et PREG_UNMATCHED_AS_NULL, qui influence le format du tableau de correspondances. Voir la description de preg_match() pour plus de détail.

Valeurs de retour

preg_replace_callback() retourne un tableau si le paramètre subject est un tableau, ou, sinon, une chaîne de caractères. Si une erreur survient, la valeur retournée sera null.

Si des correspondances sont trouvées, le nouveau sujet sera retourné, sinon subject sera retourné inchangé.

Erreurs / Exceptions

Si le masque regex passé ne compile pas à une regex valide, une E_WARNING est émise.

Historique

Version Description
7.4.0 Le paramètre flags a été ajouté.

Exemples

Exemple #2 Exemple avec preg_replace_callback()

<?php
// Ce texte était vrai en 2002
// nous voulons le mettre a jour pour 2003
$text = "Le premier avril est le 04/01/2002\n";
$text.= "Le dernier noël était le 12/24/2001\n";

// Fonction de callback
function next_year($matches)
{
// comme d'habitude : $matches[0] représente la valeur totale
// $matches[1] représente la première parenthèse capturante
return $matches[1].($matches[2]+1);
}
echo
preg_replace_callback(
"|(\d{2}/\d{2}/)(\d{4})|",
"next_year",
$text);

?>

L'exemple ci-dessus va afficher :

Le premier avril est le 04/01/2003
Le dernier noël était le 12/24/2002

Exemple #3 Exemple avec preg_replace_callback() en utilisant une structure récursive pour gérer du BB code

<?php
$input
= "plain [indent] deep [indent] deeper [/indent] deep [/indent] plain";

function
parseTagsRecursive($input)
{

$regex = '#\[indent]((?:[^[]|\[(?!/?indent])|(?R))+)\[/indent]#';

if (
is_array($input)) {
$input = '<div style="margin-left: 10px">'.$input[1].'</div>';
}

return
preg_replace_callback($regex, 'parseTagsRecursive', $input);
}

$output = parseTagsRecursive($input);

echo
$output;
?>

Voir aussi

add a note

User Contributed Notes 12 notes

up
105
Richard
13 years ago
The easiest way to pass more than one parameters to the callback function is with the 'use' keyword. 

[This is better than using global, because it works even when we are already inside a function.]

In this example, the callback function is an anonymous function, which takes one argument, $match, supplied by preg_replace_callback().  The extra 
"use ($ten)" puts the $ten variable into scope for the function.

<?php
$string = "Some numbers: one: 1; two: 2; three: 3 end";
$ten = 10;
$newstring = preg_replace_callback(
    '/(\\d+)/',
    function($match) use ($ten) { return (($match[0] + $ten)); },
    $string
    );
echo $newstring;
#prints "Some numbers: one: 11; two: 12; three: 13 end";
?>
up
10
Sjon at hortensius dot net
18 years ago
preg_replace_callback returns NULL when pcre.backtrack_limit is reached; this sometimes occurs faster then you might expect. No error is raised either; so don't forget to check for NULL yourself
up
24
Yuri
13 years ago
If you want to call non-static function inside your class, you can do something like this. 

For PHP 5.2 use second argument like array($this, 'replace'):
<?php
class test_preg_callback{

  private function process($text){
    $reg = "/\{([0-9a-zA-Z\- ]+)\:([0-9a-zA-Z\- ]+):?\}/";
    return preg_replace_callback($reg, array($this, 'replace'), $text);
  }
  
  private function replace($matches){
    if (method_exists($this, $matches[1])){
      return @$this->$matches[1]($matches[2]);     
    }
  }  
}
?>

For PHP 5.3 use second argument like "self::replace":
<?php
class test_preg_callback{

  private function process($text){
    $reg = "/\{([0-9a-zA-Z\- ]+)\:([0-9a-zA-Z\- ]+):?\}/";
    return preg_replace_callback($reg, "self::replace", $text);
  }
  
  private function replace($matches){
    if (method_exists($this, $matches[1])){
      return @$this->$matches[1]($matches[2]);     
    }
  }  
}
?>
up
3
carlos dot ballesteros at softonic dot com
16 years ago
A simple function to replace a list of complete words or terms in a string (for PHP 5.3 or above because of the closure):

<?php
function replace_words($list, $line, $callback) {
    return preg_replace_callback(
        '/(^|[^\\w\\-])(' . implode('|', array_map('preg_quote', $list)) . ')($|[^\\w\\-])/mi',
        function($v) use ($callback) { return $v[1] . $callback($v[2]) . $v[3]; },
        $line
    );
}
?>

Example of usage:
<?php
$list = array('php', 'apache web server');
$str = "php and the apache web server work fine together. php-gtk, for example, won't match. apache web servers shouldn't too.";

echo replace_words($list, $str, function($v) {
    return "<strong>{$v}</strong>";
});
?>
up
2
matt at mattsoft dot net
19 years ago
it is much better on preformance and better practice to use the preg_replace_callback function instead of preg_replace with the e modifier.

function a($text){return($text);}

// 2.76 seconds to run 50000 times
preg_replace("/\{(.*?)\}/e","a('\\1','\\2','\\3',\$b)",$a);

// 0.97 seconds to run 50000 times
preg_replace_callback("/\{(.*?)\}/s","a",$a);
up
5
Fredow
10 years ago
<?php
// Nice little function that convert a string to uppercase by keeping the HTMLentities intact.
public static function strtoupper_entities($str) {

    $patternMajEntities = '/(\&([A-Z])(ACUTE|CEDIL|CARON|CIRC|GRAVE|ORN|RING|SLASH|TH|TILDE|UML)\;)+/';
    $str = preg_replace_callback ($patternMajEntities, 
        function ($matches) {
            return "&" . $matches[2] . strtolower($matches[3]) . ";";
        }, strtoupper($str));
    
    return $str;
}
up
2
Drake
15 years ago
The good version of the class PhpHex2Str
<?php
class PhpHex2Str
{
    private $strings;

    private static function x_hex2str($hex) {
        $hex = substr($hex[0], 1);
        $str = '';
        for($i=0;$i < strlen($hex);$i+=2) {
            $str.=chr(hexdec(substr($hex,$i,2)));
        }
        return $str;
    }

    public function decode($strings = null) {
        $this->strings = (string) $strings;
        return preg_replace_callback('#\%[a-zA-Z0-9]{2}#', 'PhpHex2Str::x_hex2str', $this->strings);
    }
}

// Exemple
$obj = new PhpHex2Str;

$strings = $obj->decode($strings);
var_dump($strings);
?>
up
2
T-Soloveychik at ya dot ru
12 years ago
Text lines numeration:
<?PHP
// Multieline text:
    $Text = "
Some 
Multieline
text
for
numeration";

// For count:
    $GLOBALS["LineNUMBER"] = 1;

// Replace linestart on number:
    PRINT preg_replace_callback("/^/m",function ()
        {
            return $GLOBALS["LineNUMBER"]++."  ";
        },
        $Text);

?>

1
2 Some
3 Multieline
4 text
5 for
6 numeration
up
4
development at HashNotAdam dot com
13 years ago
From PHP 5.3 you can use an anonymous function to pass local variables into the callback.

<?php

public function replace_variables( $subject, $otherVars ) {
    $linkPatterns = array(
        '/(<a .*)href=(")([^"]*)"([^>]*)>/U',
        "/(<a .*)href=(')([^']*)'([^>]*)>/U"
    );

    $callback = function( $matches ) use ( $otherVars ) {
        $this->replace_callback($matches, $otherVars);
    };

    return preg_replace_callback($this->patterns, $callback, $subject);
}

public function replace_callback($matches, $otherVars) {
    return $matches[1] . $otherVars['myVar'];
}
?>
up
1
chris at ocproducts dot com
15 years ago
The pcre.backtrack_limit option (added in PHP 5.2) can trigger a NULL return, with no errors. The default pcre.backtrack_limit value is 100000. If you have a match that exceeds about half this limit it triggers a NULL response.
e.g. My limit was at 100000 but 500500 triggered a NULL response. I'm not running unicode but I *guess* PCRE runs in utf-16.
up
2
Evgeny
2 years ago
Please note! if you have defined namespace,
the usage format must me changed:

echo preg_replace_callback(
            "|(\d{2}/\d{2}/)(\d{4})|",
            __NAMESPACE__ . '\\next_year',
            $text);
up
0
steven at nevvix dot com
7 years ago
<?php
$format = <<<SQL
CREATE DATABASE IF NOT EXISTS :database;
GRANT ALL PRIVILEGES ON :database_name.* TO ':user'@':host';
SET PASSWORD = PASSWORD(':pass');
SQL;
$args = ["database"=>"people", "user"=>"staff", "pass"=>"pass123", "host"=>"localhost"];

preg_replace_callback("/:(\w+)/", function ($matches) use ($args) {
    return @$args[$matches[1]] ?: $matches[0];
}, $format);

/*
Result:

CREATE DATABASE IF NOT EXISTS people;
GRANT ALL PRIVILEGES ON :database_name.* TO 'staff'@'localhost';
SET PASSWORD = PASSWORD('pass123');

The `:database_name` placeholder doesn't exist as a matching key in `$args` so it's returned as is.
This way you know you need to correct the array by adding the "database_name" item.
*/
To Top