2010-02-21 39 views
7

¿Hay alguna manera de poner un comodín en una cadena? La razón por la que pregunto es porque actualmente tengo una función para buscar una subcadena entre dos subcadenas (es decir, tomar el contenido entre "mi" y "tiene pulgas" en la oración "mi perro tiene pulgas", lo que resulta en "perro")Cadena de búsqueda php (con comodines)

function get_string_between($string, $start, $end){ 
    $string = " ".$string; 
    $ini = strpos($string,$start); 
    if ($ini == 0) return ""; 
    $ini += strlen($start); 
    $len = strpos($string,$end,$ini) - $ini; 
    return substr($string,$ini,$len); 
} 

Lo que quiero hacer es tener que buscar con un comodín en la cadena. Así que digamos que busco entre "% WILDCARD%" y "tiene pulgas" en la oración "Mi perro tiene pulgas" - todavía saldría "perro".

No sé si lo expliqué demasiado bien pero espero que alguien me entienda: P. ¡Muchas gracias por leer!

+1

si quieres comodines, puede utilizar expresiones regulares en su lugar. – ghostdog74

+0

muchas gracias chicos, de verdad! – Baehr

Respuesta

8

Este es uno de los pocos casos en que las expresiones regulares son realmente útiles. :)

if (preg_match('/my (\w+) has/', $str, $matches)) { 
    echo $matches[1]; 
} 

Consulte la documentación para preg_match.

+10

Eso es simplemente ignorante, las expresiones regulares son excelentes herramientas. – raveren

+0

@Raveren: Las expresiones regulares son herramientas terribles en la mano de los tontos. Muchas personas las usan sin entender sus limitaciones, qué tipo de motores existen, etc. – Christian

+15

* Las expresiones regulares son herramientas terribles en manos de los tontos. * Así que es literalmente cualquier otra herramienta que existe. – raveren

2

Usa un regex.

$string = "My dog has fleas"; 
if (preg_match("/\S+ (\S+) has fleas/", $string, $matches)) 
    echo ($matches[1]); 
else 
    echo ("Not found"); 

\S significa cualquier carácter no-espacio, + significa que uno o más de lo anterior, por lo que significa \S+ partido de uno o más caracteres no espaciales. (…) significa capturar el contenido de la subcoincidencia y ponerla en la matriz $matches.

0

Si insiste en usar comodines (y sí, PREG es mucho mejor) puede usar la función fnmatch que funciona solo en * NIX.

Saludos

3

que coinciden en que expresiones regulares son mucho más flexibles que los comodines, pero a veces lo que quieres es una forma sencilla de definir patrones. Para las personas que buscan una solución portátil (no * NIX solamente) aquí está mi implementación de la función:

function wild_compare($wild, $string) { 
    $wild_i = 0; 
    $string_i = 0; 

    $wild_len = strlen($wild); 
    $string_len = strlen($string); 

    while ($string_i < $string_len && $wild[$wild_i] != '*') { 
     if (($wild[$wild_i] != $string[$string_i]) && ($wild[$wild_i] != '?')) { 
      return 0; 
     } 
     $wild_i++; 
     $string_i++; 
    } 

    $mp = 0; 
    $cp = 0; 

    while ($string_i < $string_len) { 
     if ($wild[$wild_i] == '*') { 
      if (++$wild_i == $wild_len) { 
       return 1; 
      } 
      $mp = $wild_i; 
      $cp = $string_i + 1; 
     } 
     else 
     if (($wild[$wild_i] == $string[$string_i]) || ($wild[$wild_i] == '?')) { 
      $wild_i++; 
      $string_i++; 
     } 
     else { 
      $wild_i = $mp; 
      $string_i = $cp++; 
     } 
    } 

    while ($wild[$wild_i] == '*') { 
     $wild_i++; 
    } 

    return $wild_i == $wild_len ? 1 : 0; 
} 

Naturalmente, la aplicación PHP es más lento que fnmatch(), pero funcionaría en cualquier plataforma.

Se puede utilizar como esto:

if (wild_compare('regex are * useful', 'regex are always useful') == 1) { 
    echo "I'm glad we agree on this"; 
} 
+0

¡agradable! tuvimos el requisito de permitir que nuestro personal ingrese reglas de expresiones regulares para hacer coincidir ciertos datos. Como no entienden la expresión regular, ¡esta fue la solución perfecta! – Luc

1

patrón de comodines puede ser convertido a patrón de expresión regular como este

function wildcard_match($pattern, $subject) { 
    $pattern = strtr($pattern, array(
    '*' => '.*?', // 0 or more (lazy) - asterisk (*) 
    '?' => '.', // 1 character - question mark (?) 
)); 
    return preg_match("/$pattern/", $subject); 
} 

si contenido de la cadena caracteres especiales, por ejemplo, .? \ + *^$ | {}/'#, Que debe ser \ -escape

no probado:

function wildcard_match($pattern, $subject) { 
    // quotemeta function has most similar behavior, 
    // it escapes \.+*?^$[](), but doesn't escape |{}/'# 
    // we don't include * and ? 
    $special_chars = "\.+^$[]()|{}/'#"; 
    $special_chars = str_split($special_chars); 
    $escape = array(); 
    foreach ($special_chars as $char) $escape[$char] = "\\$char"; 
    $pattern = strtr($pattern, $escape); 
    $pattern = strtr($pattern, array(
    '*' => '.*?', // 0 or more (lazy) - asterisk (*) 
    '?' => '.', // 1 character - question mark (?) 
)); 
    return preg_match("/$pattern/", $subject); 
} 
+0

Debería haber un posible preg_quote en el patrón $ – velop

Cuestiones relacionadas