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.

Fabio Mora
fuente
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);
Tatu Ulmanen
fuente
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;
}
Pavel
fuente
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);
cbrandolino
fuente
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.

Inca
fuente
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
Aleksandar Bosakov
fuente
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));
Stefan Gabos
fuente
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));
Muzaffar Mahmood
fuente
-1
<?php
$str = 'bla_string_bla_bla_bla';
echo preg_replace('/bla_/', '', $str, 1); 
?>
Bhanu Prakash Pandey
fuente
-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);
Pantano
fuente
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.");
usuario1016724
fuente
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