Usuń ciąg z początku łańcucha

146

Mam ciąg, który wygląda tak:

$str = "bla_string_bla_bla_bla";

Jak mogę usunąć pierwszy bla_; ale tylko wtedy, gdy znajduje się na początku ciągu?

Dzięki str_replace()temu usuwa wszystko bla_ .

Alex
źródło
1
Może okazać się s($str)->replacePrefix('_bla')pomocny, co znajdziesz w tej samodzielnej bibliotece .
krakaj

Odpowiedzi:

339

Forma zwykła, bez wyrażenia regularnego:

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

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

Trwa: 0,0369 ms (0,000 036,954 sekund)

I z:

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

Trwa: 0,1749 ms (0,000174,999 sekund) pierwsze uruchomienie (kompilacja) i 0,0510 ms (0,000 051 021 sekund) później.

Oczywiście profilowane na moim serwerze.

Fabio Mora
źródło
8
Nigdy nie widziałem, aby operator trójskładnikowy był tak nadużywany, prosty if(condition) { statement }byłby o wiele jaśniejszy.
Tatu Ulmanen
4
@salathe: Przyjmuję krytykę. Osobistą ciekawością było zobaczyć, co jest najszybsze.
Fabio Mora
51
@ salathe, nie rozumiem. Zaproponowano rozwiązania zarówno idiomatyczne, jak i oparte na regexach: porównanie obu pod względem wydajności pomaga znaleźć najlepszą (ponownie pod względem wydajności) odpowiedź. Dlaczego to jest złe?
cbrandolino
5
@cbrandolino, nikt nie powiedział, że to zło . Po prostu pomyślałem, że to całkowicie nieistotne dla pytania; podobnie jak „tutaj są dwa rozwiązania, a oto zdjęcie kilku kociąt, aby uzyskać więcej głosów za”.
salathe
5
if (substr($str, 0, strlen($prefix)) == $prefix) można zmienić na, if (0 === strpos($str, $prefix))aby uniknąć niepotrzebnego przydziału pamięci przy zachowaniu tej samej czytelności :)
xDaizu
63

Możesz użyć wyrażeń regularnych z symbolem daszka ( ^), który zakotwicza dopasowanie na początku ciągu:

$str = preg_replace('/^bla_/', '', $str);
Tatu Ulmanen
źródło
Zastanawiam się, czy działa szybciej niż substr()wersja ... Myślę, że tak i należy to zaznaczyć jako właściwą odpowiedź.
Flash Thunder
z wyjątkiem tego, że musi to być preg_quote„d
vp_arth
Myślę, że jest to o wiele mniej bolesne dla oczu programisty i bardziej intuicyjne. Nawet jeśli traci wydajność na inne sugerowane rozwiązanie (w które naprawdę wątpię), i tak wolałbym to.
Fr0zenFyr,
multibytekoszmar to kolejny problem z innymi rozwiązaniami, ale działa to dobrze, jeśli kodowanie pliku jest poprawne. Zresztą to nie powinno wchodzić w zakres tego pytania, więc nie obchodzi mnie to.
Fr0zenFyr,
Wróciłem, aby wspomnieć, że ma to dodatkową zaletę pracy z tablicą ciągów tematów. substri strposnie może zaakceptować tablicy. Proszę bardzo, wyraźny wzrost wydajności, jeśli masz do czynienia z tablicą. Twoje zdrowie!
Fr0zenFyr,
20
function remove_prefix($text, $prefix) {
    if(0 === strpos($text, $prefix))
        $text = substr($text, strlen($prefix)).'';
    return $text;
}
Pavel
źródło
10
Nie .''jest potrzebne.
NateS
1
Na ile to jest warte, ponieważ każdy wydaje się tutaj mikrooptymalizować, ten jest konsekwentnie najszybszy według moich obliczeń. 1 milion iteracji pojawiło się w 0,17 sekundy, podczas gdy (substr($str, 0, strlen($prefix)) == $prefix)z zaakceptowanej odpowiedzi było bardziej jak
0,37
5

Tutaj.

$array = explode("_", $string);
if($array[0] == "bla") array_shift($array);
$string = implode("_", $array);
cbrandolino
źródło
2
Zmierz 0,0000459153 sekundy :)
Fabio Mora,
Niezła prędkość, ale jest to zakodowane na stałe w zależności od igły kończącej się _. Czy istnieje wersja ogólna?
toddmo
0

Myślę, że substr_replace robi to, co chcesz, gdzie możesz ograniczyć zamianę do części twojego ciągu: http://nl3.php.net/manual/en/function.substr-replace.php (To pozwoli ci spojrzeć tylko na początek ciągu.)

Możesz użyć parametru count w str_replace ( http://nl3.php.net/manual/en/function.str-replace.php ), pozwoli to ograniczyć liczbę wymian, zaczynając od lewej, ale nie wymusi tego na początku.

Inca
źródło
1
substr_replacezamieni znaki w podanym zakresie niezależnie od tego, czy są to przedrostki, które chcesz usunąć, czy coś innego. Operator chce usunąć bla_„tylko wtedy, gdy zostanie znaleziony na początku ciągu”.
Olivier „Ölbaum” Scherler
0

Niezła prędkość, ale jest to zakodowane na stałe w zależności od igły kończącej się na _. Czy istnieje wersja ogólna? - toddmo 29 czerwca o 23:26

Wersja ogólna:

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

Niektóre testy porównawcze:

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

Na moim dość starym komputerze domowym:

$ php bench.php

Wyjścia:

   strpos+strlen : 0.158388 s
         explode : 0.126772 s
Aleksandar Bosakov
źródło
0

Oto jeszcze szybsze podejście:

// 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
źródło
0

Spowoduje to usunięcie pierwszego dopasowania, gdziekolwiek zostanie znalezione, tj. Początek, środek lub koniec.

$str = substr($str, 0, strpos($str, $prefix)).substr($str, strpos($str, $prefix)+strlen($prefix));
Muzaffar Mahmood
źródło
-1
<?php
$str = 'bla_string_bla_bla_bla';
echo preg_replace('/bla_/', '', $str, 1); 
?>
Bhanu Prakash Pandey
źródło
-6

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

teraz robi co chcesz.

$str = "bla_string_bla_bla_bla";
str_replace("bla_","",$str,1);
Bagno
źródło
7
W str_replace()funkcyjnego $countOczekuje się parametr być zmienna przekazywana przez odniesienie do zawierać liczbę wymian znaleźć, nie ogranicza liczby wymian.
AL the X
-6

Usuń www. od początku napisu, to jest najłatwiejszy sposób (ltrim)

$a="www.google.com";
echo ltrim($a, "www.");
user1016724
źródło
8
Drugi parametr to mapa znaków do usunięcia z lewej strony ciągu ( php.net/manual/function.ltrim.php ). Dlatego: ltrim($a, "w.");wykonałby zadanie tylko wtedy, gdyby domena nie zaczynała się od litery „w”. ltrim ('m.google.com', ".omg")powoduje le.com.
fragmentaryczna rzeczywistość
ale to rozwiązuje konkretny problem pytania, +1
chulian
1
to naprawdę rozwiązuje konkretny problem, który stworzył dla swojej odpowiedzi - nie problem pytania. nawet jeśli byś poszedł z ltrim, jest używany nieprawidłowo. drugi parametr to lista znaków, które należy przyciąć; dlatego jeden "w."byłby wystarczający.
fragmentedreality
Myślę, IMHO, to jest poprawne w przypadku pytań i problemów.
abkrim,
2
Po teście z kilkoma testami zmień moją opinię ... nie działa na pytanie w żadnej sytuacji
abkrim