Remover uma sequência do início de uma sequência

146

Eu tenho uma string que se parece com isso:

$str = "bla_string_bla_bla_bla";

Como posso remover o primeiro bla_; mas somente se for encontrado no início da string?

Com str_replace(), remove todos bla_ .

Alex
fonte
1
Você pode achar s($str)->replacePrefix('_bla')útil, conforme encontrado nesta biblioteca autônoma .
caw

Respostas:

339

Forma simples, sem regex:

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

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

Leva: 0,0369 ms (0,000,036,954 segundos)

E com:

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

Leva: 0,1749 ms (0,000,174,999 segundos) na 1ª execução (compilando) e 0,0510 ms (0,000,051,021 segundos) depois.

Perfilado no meu servidor, obviamente.

Fabio Mora
fonte
8
Eu nunca vi o operador ternário sofrer tanto abuso, um simples if(condition) { statement }teria sido muito mais claro.
Tatu Ulmanen
4
@ salathe: Eu aceito as críticas. Era uma curiosidade pessoal ver o que era mais rápido.
Fabio Mora
51
@ salathe, eu não entendo. Foram propostas soluções idiomáticas e baseadas em regex: comparar as duas em termos de eficiência ajuda a encontrar a melhor resposta (novamente em termos de eficiência). Por que isso é mau?
Cbrandolino
5
@cbrandolino, ninguém disse que era mau . Eu apenas pensei que era totalmente irrelevante para a pergunta; muito parecido com "aqui estão duas soluções, e aqui está uma foto de alguns gatinhos para mais votos" seria.
Salathe
5
if (substr($str, 0, strlen($prefix)) == $prefix) pode ser alterado para if (0 === strpos($str, $prefix))evitar a alocação de memória desnecessária, mantendo a mesma legibilidade :)
xDaizu
63

Você pode usar expressões regulares com o símbolo de sinal de intercalação ( ^) que ancora a correspondência no início da sequência:

$str = preg_replace('/^bla_/', '', $str);
Tatu Ulmanen
fonte
Gostaria de saber se funciona mais rápido que a substr()versão ... Acho que funciona, e deve ser marcado como resposta adequada.
Flash Thunder
exceto que deve ser preg_quote'd
vp_arth
Eu acho que isso é muito menos doloroso para os olhos de um programador e mais intuitivo. Mesmo se perder no desempenho para outra solução sugerida (da qual realmente duvido), ainda assim prefiro isso.
Fr0zenFyr
multibytepesadelo é outro problema com outras soluções, enquanto isso funciona bem se a codificação do arquivo estiver correta. De qualquer forma, não deveria estar no escopo desta pergunta, para que eu não me importasse.
Fr0zenFyr
Voltamos a mencionar que isso tem um benefício adicional de trabalhar com uma variedade de sequências de assuntos. substre strposnão pode aceitar uma matriz. Lá está, um ganho de desempenho definitivo se você estiver lidando com uma matriz. Felicidades!
Fr0zenFyr
20
function remove_prefix($text, $prefix) {
    if(0 === strpos($text, $prefix))
        $text = substr($text, strlen($prefix)).'';
    return $text;
}
Pavel
fonte
10
O .''não é necessário.
NateS 11/11
1
Pelo que vale a pena, já que todo mundo parece estar otimizando aqui, este é consistentemente mais rápido pela minha contagem. 1 milhão de iterações ficou em 0,17 segundos, enquanto que (substr($str, 0, strlen($prefix)) == $prefix)a partir da resposta aceita foi mais como 0,37
billynoah
5

Aqui.

$array = explode("_", $string);
if($array[0] == "bla") array_shift($array);
$string = implode("_", $array);
cbrandolino
fonte
2
Meça 0.0000459153 segundos :)
Fabio Mora
Boa velocidade, mas isso é codificado para depender da agulha que termina com _. Existe uma versão geral?
toddmo
0

Eu acho que substr_replace faz o que você quer, onde você pode limitar sua substituição a parte da sua string: http://nl3.php.net/manual/en/function.substr-replace.php (Isso permitirá que você veja apenas o início da string.)

Você pode usar o parâmetro count de str_replace ( http://nl3.php.net/manual/en/function.str-replace.php ), isso permitirá que você limite o número de substituições, começando pela esquerda, mas não fará com que seja no início.

Inca
fonte
1
substr_replacesubstituirá os caracteres no intervalo especificado, independentemente de serem o prefixo que você deseja remover ou outra coisa. O OP quer remover bla_"apenas se for encontrado no início da string".
Olivier 'Ölbaum' Scherler 31/03
0

Velocidade agradável, mas isso é codificado para depender da agulha que termina com _. Existe uma versão geral? - toddmo 29/06 às 23:26

Uma versão geral:

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

Alguns benchmarks:

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

No meu PC doméstico bastante antigo:

$ php bench.php

Saídas:

   strpos+strlen : 0.158388 s
         explode : 0.126772 s
Aleksandar Bosakov
fonte
0

Aqui está uma abordagem ainda mais rápida:

// 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
fonte
0

Isso removerá a primeira correspondência onde quer que seja encontrada, isto é, início ou meio ou fim.

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

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

agora faz o que você quer.

$str = "bla_string_bla_bla_bla";
str_replace("bla_","",$str,1);
Pântano
fonte
7
A str_replace()da função $countparâmetro deverá ser uma variável passada por referência para conter o número de substituições encontrado, não limitar o número de substituições.
AL o X
-6

Retire www. desde o início da string, esta é a maneira mais fácil (ltrim)

$a="www.google.com";
echo ltrim($a, "www.");
user1016724
fonte
8
O segundo parâmetro é um mapa de caracteres a serem removidos do lado esquerdo da string ( php.net/manual/function.ltrim.php ). Portanto: ltrim($a, "w.");faria o trabalho apenas se o domínio não iniciar com um "w". ltrim ('m.google.com', ".omg")resulta em le.com.
Fragmentedreality
mas resolve o problema específico da questão, +1
chulian 05/04
1
ele realmente resolve o problema específico que ele fez para sua resposta - não o problema da pergunta. mesmo se você escolher ltrim, ele será usado incorretamente. o segundo parâmetro é uma lista de caracteres que devem ser aparados; portanto, um único "w."seria suficiente.
Fragmentedreality
Eu acho que, IMHO, é correto para perguntas e problemas.
abkrim
2
Após o teste com vários testes mudar minha opinião .... não trabalho para a pergunta sobre quaisquer situações
abkrim