Удалить строку из начала строки

Ответы:

345

Простая форма без регулярного выражения:

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

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

Требуется : 0,0369 мс (0,000 036,954 секунды)

И с:

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

Требуется : 0,1749 мс (0,000 174 999 секунд) при первом запуске (компиляция) и 0,0510 мс (0,000 051 021 секунда) после.

Очевидно, профилированы на моем сервере.

Фабио Мора
источник
8
Я никогда не видел, чтобы тернарный оператор злоупотребляли так сильно, простой if(condition) { statement }был бы намного понятнее.
Тату Улманен
4
@salathe: Я принимаю критику. Было личным любопытством увидеть, что будет быстрее всего.
Фабио Мора
51
@salathe, я не понимаю. Были предложены как идиоматические решения, так и решения на основе регулярных выражений: сравнение этих двух с точки зрения эффективности помогает найти лучший (опять же с точки зрения эффективности) ответ. Почему это зло?
cbrandolino
5
@cbrandolino, никто не сказал, что это зло . Я просто подумал, что это совершенно не имеет отношения к вопросу; во многом как «вот два решения, а вот изображение котят, получивших больше голосов».
Салате
5
if (substr($str, 0, strlen($prefix)) == $prefix) может быть изменен, if (0 === strpos($str, $prefix))чтобы избежать ненужного выделения памяти при сохранении той же читабельности :)
xDaizu 01
63

Вы можете использовать регулярные выражения с символом вставки ( ^), который привязывает совпадение к началу строки:

$str = preg_replace('/^bla_/', '', $str);
Тату Улманен
источник
Интересно, работает ли он быстрее, чем substr()версия ... Я думаю, что да, и должен быть отмечен как правильный ответ.
Flash Thunder
за исключением того, что это должно быть preg_quote'd
vp_arth
Я думаю, что это гораздо менее болезненно для глаз программиста и более интуитивно понятно. Даже если он проигрывает другому предлагаемому решению (в чем я действительно сомневаюсь), я все равно предпочел бы это.
Fr0zenFyr
multibyteкошмар - еще одна проблема с другими решениями, хотя это хорошо работает, если кодировка файла правильная. В любом случае, это не должно входить в рамки этого вопроса, поэтому мне было бы все равно.
Fr0zenFyr
Вернулся, чтобы упомянуть, что это дает дополнительное преимущество работы с массивом строк темы. substrи strposне может принять массив. Вот и все, определенное увеличение производительности, если вы имеете дело с массивом. Ура!
Fr0zenFyr
20
function remove_prefix($text, $prefix) {
    if(0 === strpos($text, $prefix))
        $text = substr($text, strlen($prefix)).'';
    return $text;
}
Павел
источник
10
Это .''не нужно.
NateS
1
Что бы это ни стоило, поскольку здесь все, кажется, микрооптимизируются, этот, по моим подсчетам, неизменно самый быстрый. 1 миллион итераций произошел за 0,17 секунды, тогда как (substr($str, 0, strlen($prefix)) == $prefix)из принятого ответа было больше похоже на
0,37
5

Вот.

$array = explode("_", $string);
if($array[0] == "bla") array_shift($array);
$string = implode("_", $array);
Cbrandolino
источник
2
Измерьте 0.0000459153 секунды :)
Fabio Mora
Хорошая скорость, но она жестко запрограммирована в зависимости от иглы, на которую заканчивается _. Есть общая версия?
toddmo
1

Вот еще более быстрый подход:

// strpos is faster than an unnecessary substr() and is built just for that 
if (strpos($str, $prefix) === 0) $str = substr($str, strlen($prefix));
Стефан Габос
источник
0

Я думаю, что substr_replace делает то, что вы хотите, где вы можете ограничить замену частью своей строки: http://nl3.php.net/manual/en/function.substr-replace.php (Это позволит вам смотреть только на начало строки.)

Вы можете использовать параметр count str_replace ( http://nl3.php.net/manual/en/function.str-replace.php ), это позволит вам ограничить количество замен, начиная слева, но это не будет заставлять это быть в начале.

Инки
источник
1
substr_replaceзаменит символы в заданном диапазоне независимо от того, хотите ли вы удалить префикс или что-то еще. OP хочет удалить, bla_«только если он находится в начале строки».
Оливье «Олбаум» Шерлер,
0

Хорошая скорость, но она жестко запрограммирована в зависимости от стрелки, оканчивающейся на _. Есть общая версия? - toddmo 29 июня в 23:26

Общая версия:

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

Некоторые тесты:

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

На моем довольно старом домашнем ПК:

$ php bench.php

Выходы:

   strpos+strlen : 0.158388 s
         explode : 0.126772 s
Александр Босаков
источник
0

Это удалит первое совпадение, где бы оно ни было, то есть начало, середину или конец.

$str = substr($str, 0, strpos($str, $prefix)).substr($str, strpos($str, $prefix)+strlen($prefix));
Музаффар Махмуд
источник
-1
<?php
$str = 'bla_string_bla_bla_bla';
echo preg_replace('/bla_/', '', $str, 1); 
?>
Бхану Пракаш Пандей
источник
-6

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

теперь делает то, что вы хотите.

$str = "bla_string_bla_bla_bla";
str_replace("bla_","",$str,1);
Болото
источник
7
Ожидается, str_replace()что $countпараметром функции будет переменная, переданная по ссылке и содержащая количество найденных замен, а не ограничение количества замен.
AL the X
-6

Удалите www. от начала строки, это самый простой способ (ltrim)

$a="www.google.com";
echo ltrim($a, "www.");
user1016724
источник
8
Второй параметр - это карта символов, которые нужно удалить с левой стороны строки ( php.net/manual/function.ltrim.php ). Следовательно: ltrim($a, "w.");будет выполнять работу только в том случае, если домен не начинается с буквы «w». ltrim ('m.google.com', ".omg")приводит к le.com.
fragmentedreality
но он решает конкретную проблему вопроса, +1
chulian 05
1
это действительно решает конкретную проблему, которую он поставил для своего ответа, а не проблему вопроса. даже если бы вы пошли ltrim, он используется неправильно. второй параметр - это список символов, которые следует обрезать; поэтому одного "w."будет достаточно.
fragmentedreality
Я думаю, ИМХО, это правильно для вопроса и для проблемы.
abkrim
2
После теста с несколькими тестами мое мнение изменилось .... не
подходит