Foros del Web » Programando para Internet » PHP »

[SOLUCIONADO] preg_replace_callback bug?

Estas en el tema de preg_replace_callback bug? en el foro de PHP en Foros del Web. Buenas, tengo un problema medio raro con el preg_replace_callback.. pego el codigo y el output para que lo vean... (viendo el index.php y el output ...
  #1 (permalink)  
Antiguo 27/07/2015, 03:19
Avatar de Fernand0  
Fecha de Ingreso: septiembre-2005
Ubicación: Buenos Aires
Mensajes: 610
Antigüedad: 18 años, 6 meses
Puntos: 19
preg_replace_callback bug?

Buenas, tengo un problema medio raro con el preg_replace_callback.. pego el codigo y el output para que lo vean...

(viendo el index.php y el output se ve que quiero lograr)

index.php
Código PHP:
Ver original
  1. <?php
  2.    
  3.     include 'replace.php';
  4.     include 'replacer.php';
  5.    
  6.     $rplc = new Replace(
  7.         '@\.([a-z_]+)@i',
  8.         '["$1"]',
  9.         '$color.name.lala'
  10.     );
  11.    
  12.     echo "<br>replaced: " . $rplc->getReplaced();
  13.    
  14.     $rplcr = new Replacer(
  15.         '@\.([a-z_]+)@i',
  16.         '["$1"]',
  17.         '$color.name.lala'
  18.     );
  19.    
  20.     echo "<br>replacedR: " . $rplcr->getReplaced();
  21.    
  22. ?>

replace.php
Código PHP:
Ver original
  1. <?php
  2.        
  3.         class Replace
  4.         {
  5.            
  6.             private $pattern = null;
  7.            
  8.             private $replace = null;
  9.            
  10.             private $subject = null;
  11.            
  12.             private $capture = '@\$([0-9]{1,2})@i';
  13.            
  14.             private $perform = 'self::callback';
  15.            
  16.            
  17.             public function __construct($pattern, $replace, $subject)
  18.             {
  19.                
  20.                 $this->pattern = $pattern;
  21.                 $this->replace = $replace;
  22.                 $this->subject = $subject;
  23.                
  24.                 if(!$this->is_match())
  25.                     return false;
  26.                
  27.                 preg_replace_callback(
  28.                     $this->pattern,
  29.                     $this->perform,
  30.                     $this->subject
  31.                 );
  32.                
  33.             }
  34.            
  35.             private function callback($matches)
  36.             {
  37.                
  38.                 $replaced = null;
  39.                
  40.                 $callback = function($groups) use ($matches, &$replaced) {
  41.                    
  42.                     $match = $matches[$groups[1]];
  43.                    
  44.                     $replaced = str_replace(
  45.                         $groups[0],
  46.                         $match,
  47.                         $this->replace
  48.                     );
  49.                    
  50.                 };
  51.                
  52.                 preg_replace_callback(
  53.                     $this->capture,
  54.                     $callback,
  55.                     $this->replace
  56.                 );
  57.                
  58.                 $this->subject = str_replace(
  59.                     $matches[0],
  60.                     $replaced,
  61.                     $this->subject
  62.                 );
  63.                
  64.             }
  65.            
  66.             private function is_match()
  67.             {
  68.                
  69.                 $count = preg_match(
  70.                     $this->pattern,
  71.                     $this->subject
  72.                 );
  73.                
  74.                 return ($count !== 0)? true : false;
  75.                
  76.             }
  77.            
  78.             public function getReplaced()
  79.             {
  80.                
  81.                 return $this->subject;
  82.                
  83.             }
  84.            
  85.         }
  86.    
  87. ?>

replacer.php
Código PHP:
Ver original
  1. <?php
  2.    
  3.         class Replacer
  4.         {
  5.            
  6.             private $pattern = null;
  7.            
  8.             private $replace = null;
  9.            
  10.             private $subject = null;
  11.            
  12.             private $capture = '@\$([0-9]{1,2})@i';
  13.            
  14.             private $perform = 'self::callback';
  15.            
  16.            
  17.             public function __construct($pattern, $replace, $subject)
  18.             {
  19.                
  20.                 $this->pattern = $pattern;
  21.                 $this->replace = $replace;
  22.                 $this->subject = $subject;
  23.                
  24.                 if(!$this->is_match())
  25.                     return false;
  26.                
  27.                 $this->subject = preg_replace_callback(
  28.                     $this->pattern,
  29.                     $this->perform,
  30.                     $this->subject
  31.                 );
  32.                
  33.             }
  34.            
  35.             private function callback($matches)
  36.             {
  37.                
  38.                 $callback = function($groups) use ($matches) {
  39.                    
  40.                     $match = $matches[$groups[1]];
  41.                    
  42.                     return str_replace(
  43.                         $groups[0],
  44.                         $match,
  45.                         $this->replace
  46.                     );
  47.                    
  48.                 };
  49.                
  50.                 $replaced = preg_replace_callback(
  51.                     $this->capture,
  52.                     $callback,
  53.                     $this->replace
  54.                 );
  55.                
  56.                 return str_replace(
  57.                     $matches[0],
  58.                     $replaced,
  59.                     $this->subject
  60.                 );
  61.                
  62.             }
  63.            
  64.             private function is_match()
  65.             {
  66.                
  67.                 $count = preg_match(
  68.                     $this->pattern,
  69.                     $this->subject
  70.                 );
  71.                
  72.                 return ($count !== 0)? true : false;
  73.                
  74.             }
  75.            
  76.             public function getReplaced()
  77.             {
  78.                
  79.                 return $this->subject;
  80.                
  81.             }
  82.            
  83.         }
  84.    
  85. ?>

output:
Código HTML:
replaced: $color["name"]["lala"]
replacedr: $color$color["["name"]"].lala$color.name["["lala"]"]

Por alguna razon, el codigo correcto deberia ser el de "replacer.php", pero como ven en el output, devuelve cualquier cosa..

Tuve que dejar de usar el return en el preg_replace_callback.. y directamente en el callback asignarle el valor a parseado a una variable.

Si me dan una ayuda se los agradeceria
  #2 (permalink)  
Antiguo 27/07/2015, 11:52
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: preg_replace_callback bug?

¿Podrías simplificar todo tu código y sólo usar preg_replace_callback()?

Porque uno se pierde tratando de entender si el problema es tu diseño de OOP o cualquier otra cosa ahí.
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #3 (permalink)  
Antiguo 27/07/2015, 15:19
Avatar de Fernand0  
Fecha de Ingreso: septiembre-2005
Ubicación: Buenos Aires
Mensajes: 610
Antigüedad: 18 años, 6 meses
Puntos: 19
Respuesta: preg_replace_callback bug?

A ver si esto ayuda...

Código PHP:
Ver original
  1. $subject = '$color.name';
  2.    
  3.     $callback = function($matches) use ($subject) {
  4.    
  5.         $callback2 = function($groups) use ($matches) {
  6.            
  7.             $match = $matches[$groups[1]];  // $groups[1] devuelve el '1' de '$1'
  8.                                             // por tanto seria $matches[1]
  9.                                             // equivalente a 'name' (sin el punto)
  10.            
  11.             return str_replace( // duevuelvo '["name"]' para $replaced
  12.                 $groups[0], // esto tomaria cada uno de los $1 $2 encontrados..
  13.                 $match, // seria 'name'
  14.                 '["$1"]' // se reemplaza '$1' por 'name'
  15.             );
  16.            
  17.         };
  18.        
  19.         $replaced = preg_replace_callback( // consigo '["name"]'
  20.             '@\$([0-9]{1,2})@i', // busca los $1 $2 $3 etc.. que uno ponga
  21.             $callback2, // llama a $callback2
  22.             '["$1"]' // $1 deberia ser remplazado por 'name'
  23.         );
  24.        
  25.         return str_replace( // finalmente se reemplaza todo
  26.             $matches[0],  // esto es ".name"
  27.             $replaced, // esto es '["name"]'
  28.             $subject // esto es '$color.name'
  29.         );
  30.        
  31.     };
  32.    
  33.     $subject = preg_replace_callback(
  34.         '@\.([a-z_]+)@i', // busca los ".algo" en este caso ".name"
  35.         $callback, // llama a $callback
  36.         $subject // string = '$color.name'
  37.     );
  38.    
  39.     echo "<br>handed replaced: " . $subject;

output
Código HTML:
Ver original
  1. handed replaced: $color$color["["name"]"]
  #4 (permalink)  
Antiguo 27/07/2015, 16:00
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: preg_replace_callback bug?

¿Podrías explicar exactamente que buscas obtener?
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #5 (permalink)  
Antiguo 27/07/2015, 16:26
Avatar de Fernand0  
Fecha de Ingreso: septiembre-2005
Ubicación: Buenos Aires
Mensajes: 610
Antigüedad: 18 años, 6 meses
Puntos: 19
Respuesta: preg_replace_callback bug?

Pense que se entendia.

La idea es encontrar un patron ('@\.([a-z_]+)@i') en una cadena ($color.name) y reemplazarlo por otra cadena (["..grupo 1 del patron encontrado.."] que se leeria como ["$1"]).

Entonces encuentro ".name" en "$color.name"... y reemplazo ".name" por ["name"]... el resultado esperado seria: $color["name"]... sin embargo me devuelve: $color$color["["name"]"]

No se si se entiende ahora, su funcionamiento seria parecido al de un RewriteRule de .htaccess.. que se puede utilizar el $1.. $2.. $3... para referirse a los grupos del regex
  #6 (permalink)  
Antiguo 27/07/2015, 18:52
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: preg_replace_callback bug?

Las capturas $1 $2 y así ya las soporta PCRE por defecto (\1 \2 etc.):
Código PHP:
Ver original
  1. $regex = '@\.([a-z_]+)@i';
  2. $texto = '$color.name';
  3.  
  4. echo preg_replace($regex, '["\1"]', $texto); // $color["name"]

¿Necesitas algo más complejo?

Digo, sigo sin entender para que tanto código.
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #7 (permalink)  
Antiguo 27/07/2015, 19:24
Avatar de Fernand0  
Fecha de Ingreso: septiembre-2005
Ubicación: Buenos Aires
Mensajes: 610
Antigüedad: 18 años, 6 meses
Puntos: 19
Respuesta: preg_replace_callback bug?

what a fail..

gracias, no sabia que soportaba capturing en el replacement con el preg_replace

Igual.. no se porque el codigo cuando por ejemplo, ya consigo ["name"].. hago un echo, y el echo devuelve ["name"]... ahora cuando uso un return desde el callback, despues echo preg_replace_callback... me devuelve ["["name"]"]...
No se cual es el error del codigo la verdad.. pero bueno, me facilitaste la vida, gracias :P

Saludos
  #8 (permalink)  
Antiguo 27/07/2015, 19:33
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: preg_replace_callback bug?

Cita:
no se porque el codigo cuando por ejemplo, ya consigo ["name"].. hago un echo, y el echo devuelve ["name"]... ahora cuando uso un return desde el callback, despues echo preg_replace_callback... me devuelve ["["name"]"]
Eso se debe a lo siguiente:

preg_replace_callback() usa una función callback para el reemplazo, lo que sea que devuelvas se usará como reemplazo.

Tu error era que dentro del callback hacías tus propios reemplazos, y desde luego eso provocaba los reemplazos duplicados o mal formados, etc.
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #9 (permalink)  
Antiguo 27/07/2015, 19:47
Avatar de Fernand0  
Fecha de Ingreso: septiembre-2005
Ubicación: Buenos Aires
Mensajes: 610
Antigüedad: 18 años, 6 meses
Puntos: 19
Respuesta: preg_replace_callback bug?

Si, pero no, algo raro pasa, por eso puse el codigo..

Si pongo al final

Código PHP:
Ver original
  1.         '@\.([a-z_]+)@i',
  2.         $callback,
  3.         $subject
  4.     );

en vez de esto que venia poniendo
Código PHP:
Ver original
  1.         '@\.([a-z_]+)@i',
  2.         $callback,
  3.         $subject
  4.     );

$subject no cambia.. sigue siendo
Código HTML:
Ver original
  1. $color.name

Por alguna razon no me hace el reemplazo.
  #10 (permalink)  
Antiguo 27/07/2015, 20:11
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: preg_replace_callback bug?

Pues no, nada raro, sencillamente hacías cosas de más, trucos chinos y no se que tantos hacks para intentar darle la vuelta a algo muy simple.

Básicamente estabas usando código sin razón ni beneficio alguno:
Código PHP:
Ver original
  1. <?php
  2.  
  3. $subject = '$color.name';
  4.  
  5. // use($subject) es innecesario
  6.  
  7. $callback = function($matches) {
  8.  
  9.   /* todo esto es innecesario...
  10.  
  11.     $callback2 = function($groups) use ($matches) {
  12.  
  13.         $match = $matches[$groups[1]];  // $groups[1] devuelve el '1' de '$1'
  14.                                         // por tanto seria $matches[1]
  15.                                         // equivalente a 'name' (sin el punto)
  16.  
  17.         return str_replace( // duevuelvo '["name"]' para $replaced
  18.             $groups[0], // esto tomaria cada uno de los $1 $2 encontrados..
  19.             $match, // seria 'name'
  20.             '["$1"]' // se reemplaza '$1' por 'name'
  21.         );
  22.  
  23.     };
  24.  
  25.     $replaced = preg_replace_callback( // consigo '["name"]'
  26.         '@\$([0-9]{1,2})@i', // busca los $1 $2 $3 etc.. que uno ponga
  27.         $callback2, // llama a $callback2
  28.         '["$1"]' // $1 deberia ser remplazado por 'name'
  29.     );*/
  30.  
  31.     // esto esta mal, tu no debes hacer ningun reemplazo,
  32.     // debes dejar que preg_replace_callback haga su trabajo...
  33.  
  34.   /*
  35.     return str_replace( // finalmente se reemplaza todo
  36.         $matches[0],  // esto es ".name"
  37.         $replaced, // esto es '["name"]'
  38.         $subject // esto es '$color.name'
  39.     );
  40.     */
  41.  
  42.   // $matches[1] es "name"
  43.   return '["' . $matches[1] . '"]';
  44. };
  45.  
  46.     '@\.([a-z_]+)@i', // busca los ".algo" en este caso ".name"
  47.     $callback, // llama a $callback
  48.     $subject // string = '$color.name'
  49. );
  50.  
  51. echo "<br>handed replaced: " . $subject;

Lee bien tu código y verás que siempre hiciste mal todo.

Y todo eso ocurre por no leer el manual.
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #11 (permalink)  
Antiguo 27/07/2015, 22:52
Avatar de Fernand0  
Fecha de Ingreso: septiembre-2005
Ubicación: Buenos Aires
Mensajes: 610
Antigüedad: 18 años, 6 meses
Puntos: 19
Respuesta: preg_replace_callback bug?

Ahorrate las opiniones y suposiciones para quien te las pida...

Etiquetas: bug, return
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 11:45.