Supprimer une chaîne du début d'une chaîne


Réponses:


339

Forme simple, sans regex:

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

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

Prend: 0,0369 ms (0,000,036,954 secondes)

Et avec:

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

Prend: 0,1749 ms (0,000,174,999 secondes) la première exécution (compilation) et 0,0510 ms (0,000,051,021 secondes) après.

Profilé sur mon serveur, évidemment.


8
Je n'ai jamais vu l'opérateur ternaire aussi maltraité, un simple if(condition) { statement }aurait été tellement plus clair.
Tatu Ulmanen

4
@salathe: J'accepte les critiques. C'était une curiosité personnelle de voir ce qui était le plus rapide.
Fabio Mora

51
@salathe, je ne comprends pas. Des solutions idiomatiques et basées sur des expressions régulières ont été proposées: comparer les deux en termes d'efficacité permet de trouver la meilleure réponse (encore une fois en termes d'efficacité). Pourquoi est-ce mal?
cbrandolino

5
@cbrandolino, personne n'a dit que c'était mal . Je pensais simplement que cela n'avait aucun rapport avec la question; un peu comme "voici deux solutions, et voici une image de quelques chatons pour plus de votes positifs" serait.
salathe

5
if (substr($str, 0, strlen($prefix)) == $prefix) peut être modifié pour if (0 === strpos($str, $prefix))éviter une allocation de mémoire inutile tout en conservant la même lisibilité :)
xDaizu

63

Vous pouvez utiliser des expressions régulières avec le symbole caret ( ^) qui ancre la correspondance au début de la chaîne:

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

Je me demande si cela fonctionne plus rapidement que la substr()version ... Je suppose que c'est le cas, et devrait être marqué comme une bonne réponse.
Flash Thunder

sauf qu'il doit être preg_quote'd
vp_arth

Je pense que c'est beaucoup moins douloureux aux yeux d'un programmeur et plus intuitif. Même si cela perd en performance au profit d'une autre solution suggérée (dont je doute vraiment), je préférerais toujours celle-ci.
Fr0zenFyr

multibytecauchemar est un autre problème avec d'autres solutions alors que cela fonctionne bien si l'encodage du fichier est correct. Quoi qu'il en soit, cela ne devrait pas être dans le cadre de cette question, donc je m'en fiche.
Fr0zenFyr

Je suis revenu pour mentionner que cela présente un avantage supplémentaire de travailler avec un tableau de chaînes de sujet. substret strposne peut pas accepter un tableau. Voilà, un gain de performances certain si vous avez affaire à un tableau. À votre santé!
Fr0zenFyr

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

10
Le .''n'est pas nécessaire.
NateS du

1
Pour ce que ça vaut puisque tout le monde semble micro-optimiser ici, celui-ci est toujours le plus rapide à mon avis. 1 million d'itérations sont arrivées à 0,17 s, alors que (substr($str, 0, strlen($prefix)) == $prefix)la réponse acceptée ressemblait plus à
0,37

5

Ici.

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

2
Mesure 0,0000459153 secondes :)
Fabio Mora

Bonne vitesse, mais c'est codé en dur pour dépendre de l'aiguille se terminant par _. Existe-t-il une version générale?
toddmo

0

Je pense que substr_replace fait ce que vous voulez, où vous pouvez limiter votre remplacement à une partie de votre chaîne: http://nl3.php.net/manual/en/function.substr-replace.php (Cela vous permettra de ne regarder que le début de la chaîne.)

Vous pouvez utiliser le paramètre count de str_replace ( http://nl3.php.net/manual/en/function.str-replace.php ), cela vous permettra de limiter le nombre de remplacements, en commençant par la gauche, mais ne l’imposera pas au début.


1
substr_replaceremplacera les caractères de la plage donnée, qu'il s'agisse du préfixe que vous souhaitez supprimer ou autre. L'OP souhaite supprimer bla_"uniquement s'il se trouve au début de la chaîne".
Olivier 'Ölbaum' Scherler

0

Bonne vitesse, mais c'est codé en dur pour dépendre de l'aiguille se terminant par _. Existe-t-il une version générale? - toddmo le 29 juin à 23:26

Une version générale:

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

Quelques repères:

<?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);

Sur mon vieux PC personnel:

$ php bench.php

Les sorties:

   strpos+strlen : 0.158388 s
         explode : 0.126772 s

0

Voici une approche encore plus rapide:

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

0

Cela supprimera la première correspondance partout où elle se trouve, c'est-à-dire le début, le milieu ou la fin.

$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 ] )

fait maintenant ce que vous voulez.

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

7
Le paramètre de str_replace()la fonction $countdevrait être une variable transmise par référence pour contenir le nombre de remplacements trouvés, et non pour limiter le nombre de remplacements.
AL the X

-6

Supprimez www. depuis le début de la chaîne, c'est le moyen le plus simple (ltrim)

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

8
Le deuxième paramètre est une carte de caractères à supprimer du côté gauche de la chaîne ( php.net/manual/function.ltrim.php ). Par conséquent: ltrim($a, "w.");ne ferait le travail que si le domaine ne commencerait pas par un "w". ltrim ('m.google.com', ".omg")se traduit par le.com.
fragmentedreality

mais cela résout le problème spécifique de la question, +1
chulian

1
cela résout vraiment le problème spécifique qu'il a fait pour sa réponse - pas le problème de la question. même si vous préférez ltrim, il n'est pas utilisé correctement. le deuxième paramètre est une liste de caractères à découper; donc un seul "w."suffirait.
fragmentedreality

Je pense, à mon humble avis, que c'est correct pour la question et pour le problème.
abkrim

2
Après le test avec plusieurs tests, changez mon opinion .... ne fonctionne pas pour question sur toutes les situations
abkrim
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.