Eliminar una cadena desde el principio de una cadena


Respuestas:


339

Forma simple, sin expresión regular:

$prefix = 'bla_';
$str = 'bla_string_bla_bla_bla';

if (substr($str, 0, strlen($prefix)) == $prefix) {
    $str = substr($str, strlen($prefix));
} 

Toma: 0.0369 ms (0.000,036,954 segundos)

Y con:

$prefix = 'bla_';
$str = 'bla_string_bla_bla_bla';
$str = preg_replace('/^' . preg_quote($prefix, '/') . '/', '', $str);

Toma: 0.1749 ms (0.000,174,999 segundos) la primera ejecución (compilación) y 0.0510 ms (0.000,051,021 segundos) después.

Perfilado en mi servidor, obviamente.


8
Nunca he visto al operador ternario maltratado tanto, un simple if(condition) { statement }habría sido mucho más claro.
Tatu Ulmanen

44
@salathe: acepto las críticas. Era una curiosidad personal ver cuál era el más rápido.
Fabio Mora

51
@salathe, no lo entiendo. Se propusieron soluciones idiomáticas y basadas en expresiones regulares: comparar las dos en términos de eficiencia ayuda a encontrar la mejor respuesta (nuevamente en términos de eficiencia). ¿Por qué es eso malvado?
cbrandolino

55
@cbrandolino, nadie dijo que fuera malvado . Simplemente pensé que era completamente irrelevante para la pregunta; al igual que "aquí hay dos soluciones, y aquí hay una foto de algunos gatitos para más votos" sería.
salathe

55
if (substr($str, 0, strlen($prefix)) == $prefix) puede ser cambiado para if (0 === strpos($str, $prefix))evitar la asignación de memoria innecesaria mientras se mantiene la misma facilidad de lectura :)
xDaizu

63

Puede usar expresiones regulares con el símbolo de intercalación ( ^) que ancla la coincidencia al comienzo de la cadena:

$str = preg_replace('/^bla_/', '', $str);

Me pregunto si funciona más rápido que la substr()versión ... Supongo que sí, y debería marcarse como respuesta adecuada.
Flash Thunder

excepto que debe ser preg_quote'd
vp_arth

Creo que esto es mucho menos doloroso para los ojos de un programador y más intuitivo. Incluso si pierde rendimiento con otra solución sugerida (que realmente dudo), aún así preferiría esto.
Fr0zenFyr

multibyteLa pesadilla es otro problema con otras soluciones, mientras que esto funciona bien si la codificación del archivo es correcta. De todos modos, no debería estar en el alcance de esta pregunta, así que no me importaría.
Fr0zenFyr

Volví a mencionar que esto tiene un beneficio adicional de trabajar con una variedad de cadenas de temas. substry strposno puede aceptar una matriz. Ahí tienes, una ganancia de rendimiento definitiva si estás lidiando con una matriz. ¡Salud!
Fr0zenFyr

20
function remove_prefix($text, $prefix) {
    if(0 === strpos($text, $prefix))
        $text = substr($text, strlen($prefix)).'';
    return $text;
}

10
El .''no es necesario.
Nates

1
Por lo que vale, ya que cada uno parece estar micro optimizando aquí, este es consistentemente más rápido según mi cuenta. 1 millón de iteraciones llegaron a .17 segundos, mientras que (substr($str, 0, strlen($prefix)) == $prefix)de la respuesta aceptada fue más como .37
billynoah

5

Aquí.

$array = explode("_", $string);
if($array[0] == "bla") array_shift($array);
$string = implode("_", $array);

2
Medida 0.0000459153 segundos :)
Fabio Mora

Buena velocidad, pero esto está codificado para depender de la aguja que termina con _. ¿Hay una versión general?
toddmo

0

Creo que substr_replace hace lo que quiere, donde puede limitar su reemplazo a parte de su cadena: http://nl3.php.net/manual/en/function.substr-replace.php (Esto le permitirá mirar solo El comienzo de la cadena.)

Puede usar el parámetro count de str_replace ( http://nl3.php.net/manual/en/function.str-replace.php ), esto le permitirá limitar el número de reemplazos, comenzando desde la izquierda, pero no lo hará cumplir al principio.


1
substr_replacereemplazará los caracteres en el rango dado independientemente de si son el prefijo que desea eliminar o algo más. El OP quiere eliminar bla_"solo si se encuentra al principio de la cadena".
Olivier 'Ölbaum' Scherler

0

Buena velocidad, pero esto está codificado para depender de que la aguja termine con _. ¿Hay una versión general? - toddmo 29 de junio a las 23:26

Una versión general:

$parts = explode($start, $full, 2);
if ($parts[0] === '') {
    $end = $parts[1];
} else {
    $fail = true;
}

Algunos puntos de referencia:

<?php

$iters = 100000;
$start = "/aaaaaaa/bbbbbbbbbb";
$full = "/aaaaaaa/bbbbbbbbbb/cccccccccc/dddddddddd/eeeeeeeeee";
$end = '';

$fail = false;

$t0 = microtime(true);
for ($i = 0; $i < $iters; $i++) {
    if (strpos($full, $start) === 0) {
        $end = substr($full, strlen($start));
    } else {
        $fail = true;
    }
}
$t = microtime(true) - $t0;
printf("%16s : %f s\n", "strpos+strlen", $t);

$t0 = microtime(true);
for ($i = 0; $i < $iters; $i++) {
    $parts = explode($start, $full, 2);
    if ($parts[0] === '') {
        $end = $parts[1];
    } else {
        $fail = true;
    }
}
$t = microtime(true) - $t0;
printf("%16s : %f s\n", "explode", $t);

En mi PC casera bastante vieja:

$ php bench.php

Salidas:

   strpos+strlen : 0.158388 s
         explode : 0.126772 s

0

Aquí hay un enfoque aún más rápido:

// strpos is faster than an unnecessary substr() and is built just for that 
if (strpos($str, $prefix) === 0) $str = substr($str, strlen($prefix));

0

Esto eliminará la primera coincidencia donde se encuentre, es decir, inicio, medio o final.

$str = substr($str, 0, strpos($str, $prefix)).substr($str, strpos($str, $prefix)+strlen($prefix));


-6

str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )

ahora hace lo que quieres.

$str = "bla_string_bla_bla_bla";
str_replace("bla_","",$str,1);

77
Se espera que str_replace()el $countparámetro de la función sea ​​una variable pasada por referencia para contener el número de reemplazos encontrados, no limitar el número de reemplazos.
AL the X

-6

Eliminar www. desde el principio de la cadena, esta es la forma más fácil (ltrim)

$a="www.google.com";
echo ltrim($a, "www.");

8
El segundo parámetro es un mapa de caracteres que se eliminarán del lado izquierdo de la cadena ( php.net/manual/function.ltrim.php ). Por ltrim($a, "w.");lo tanto: haría el trabajo solo si el dominio no comenzara con una "w". ltrim ('m.google.com', ".omg")resultados en le.com.
fragmentada

pero resuelve el problema específico de la pregunta, +1
chulian

1
realmente resuelve el problema específico que hizo para su respuesta, no el problema de la pregunta. incluso si fuera con ltrim, se usa incorrectamente. el segundo parámetro es una lista de caracteres que se deben recortar; por lo tanto, un solo "w."sería suficiente.
fragmentada

Creo, en mi humilde opinión, es correcto para la pregunta y para el problema.
abkrim

2
Después de la prueba con varias pruebas cambiar mi opinión .... no trabajo para la pregunta en cualquier situación
abkrim
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.