(PHP 7, PHP 8)
preg_replace_callback_array — Realiza una búsqueda de coincidencia con una expresión regular y reemplaza mediante una función de devolución de llamada
$pattern,$subject,$limit = -1,&$count = null ,$flags = 0El comportamiento de esta función es similar a preg_replace_callback() , con la excepción de que las funciones de devolución de llamada se ejecutan para cada patrón.
patternUn array asociativo que establece una relación entre los patrones (claves) y las funciones de devolución de llamada callable (valores).
subjectLa cadena o un array que contiene las cadenas a buscar y reemplazar.
limit
El número máximo de reemplazos para cada patrón en cada
subject. Por omisión
-1 (sin límite).
countSi se proporciona, esta variable será rellenada con el número de reemplazos realizados.
flags
flags puede ser una combinación de los indicadores
PREG_OFFSET_CAPTURE y
PREG_UNMATCHED_AS_NULL , que influyen en el formato
del array de coincidencias.
Ver la descripción de preg_match() para más detalles.
preg_replace_callback_array() devuelve un array si
el parámetro subject es un array, o de lo contrario
una cadena. En caso de error, el valor devuelto es null .
Si se encuentran coincidencias, el nuevo sujeto será devuelto, de lo contrario
subject será devuelto sin cambios.
Si el patrón regex pasado no se compila a una regex válida, se emite una E_WARNING .
| Versión | Descripción |
|---|---|
| 7.4.0 |
El parámetro flags ha sido añadido.
|
Ejemplo #1 Ejemplo de preg_replace_callback_array()
<?php
$subject = 'Aaaaaa Bbb';
preg_replace_callback_array(
[
'~[a]+~i' => function ($match) {
echo strlen($match[0]), ' coincidencias de "a" encontradas', PHP_EOL;
},
'~[b]+~i' => function ($match) {
echo strlen($match[0]), ' coincidencias de "b" encontradas', PHP_EOL;
}
],
$subject
);
?>El ejemplo anterior mostrará:
6 coincidencias de "a" encontradas 3 coincidencias de "b" encontradas
Based on some tests, I found these important traits of the function. (These would
be nice to see documented as part of its spec, e.g. for confirmation. Without that,
this is just experimental curiosity. Still better than guesswork, though! ;) )
1. Changes cascade over a subject across callbacks, i.e. a change made to a
subject by a callback will be seen by the next callback, if its pattern matches
the changed subject.
(But a change made by a previous call of the *same* callback (on any subject)
will not be seen by that callback again.)
2. The pattern + callback pairs will be applied in the order of their appearance
in $patterns_and_callbacks.
3. The callback can't be null (or '') for a quick shortcut for empty replacements.
4. Overall, the algorithm starts iterating over $patterns_and_callbacks, and then
feeds each $subject to the current callback, repeatedly for every single match
of its pattern on the current subject (unlike "preg_match_all", that is, which
can do the same in one go, returning the accumulated results in an array).
This basically means that the "crown jewel", an even more efficient function:
"preg_replace_all_callback_array" is still missing from the collection.
(Of course, that would better fit a new design of the regex API, where one
API could flexibly handle various different modes via some $flags = [] array.)
5. (This last one is not specific to this function, but inherent to regexes, OTOH,
it's probably more relevant here than anywhere else in PHP's regex support.)
Even apparently simple cases can generate a crazy (and difficult-to-predict)
number of matches, and therefore callback invokations, so remember the set
$limit, where affordable. But, of course, try to sharpen your patterns first!
E.g. use ^...$ anchoring to avoid unintended extra calls on matching substrings
of a subject, (I.e. '/.*/', without anchoring, would match twice: once for the
whole subject, and then for a trailing empty substring -- but I'm not quite sure
this should actually be correct behavior, though.)finally!!!
before (<=php5.6):
<?php
$htmlString = preg_replace_callback(
'/(href="?)(\S+)("?)/i',
function (&$matches) {
return $matches[1] . urldecode($matches[2]) . $matches[3];
},
$htmlString
);
$htmlString = preg_replace_callback(
'/(href="?\S+)(%24)(\S+)?"?/i', // %24 = $
function (&$matches) {
return urldecode($matches[1] . '$' . $matches[3]);
},
$htmlString
);
?>
php7
<?php
$htmlString = preg_replace_callback_array(
[
'/(href="?)(\S+)("?)/i' => function (&$matches) {
return $matches[1] . urldecode($matches[2]) . $matches[3];
},
'/(href="?\S+)(%24)(\S+)?"?/i' => function (&$matches) {
return urldecode($matches[1] . '$' . $matches[3]);
}
],
$htmlString
);
?>Note that the first replacement is applied to the whole string before the next replacement is applied.
For example:
<?php
$subject = 'a b a b a b';
preg_replace_callback_array(
[
'/a/' => function ($match) {
echo '"a" found', PHP_EOL;
},
'/b/' => function ($match) {
echo '"b" found', PHP_EOL;
}
],
$subject
);
?>
will print
"a" found
"a" found
"a" found
"b" found
"b" found
"b" found
This means that you cannot use global variables to communicate information between the functions about what point in the string you have reached.Here's a possible alternative in older PHP.
<?php
// if (!function_exists('preg_replace_callback_array')) {
function preg_replace_callback_array (array $patterns_and_callbacks, $subject, $limit=-1, &$count=NULL) {
$count = 0;
foreach ($patterns_and_callbacks as $pattern => &$callback) {
$subject = preg_replace_callback($pattern, $callback, $subject, $limit, $partial_count);
$count += $partial_count;
}
return preg_last_error() == PREG_NO_ERROR ? $subject : NULL;
}
// }
?>