Extração de substring PHP. Obter a string antes do primeiro '/' ou a string inteira


170

Estou tentando extrair uma substring. Preciso de ajuda para fazer isso em PHP.

Aqui estão alguns exemplos de strings com os quais estou trabalhando e os resultados necessários:

home/cat1/subcat2 => home

test/cat2 => test

startpage => startpage

Eu quero pegar a string até a primeira /, mas se não /houver, pegue a string inteira.

Eu tentei,

substr($mystring, 0, strpos($mystring, '/'))

Eu acho que diz - obtenha a posição de /e, em seguida, obtenha a substring da posição 0 para essa posição.

Não sei como lidar com o caso em que não há /, sem deixar a declaração muito grande.

Existe uma maneira de lidar com esse caso também sem tornar a instrução PHP muito complexa?


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

Respostas:


261

Usar explode()

$arr = explode("/", $string, 2);
$first = $arr[0];

Neste caso, estou usando o limitparâmetro para explodeque o php não varra a string mais do que o necessário.


2
+1 Obrigado pela resposta. Funcionou :) Mas uma pergunta. Eu só sou capaz de fazer isso -> $arr = explode('/',$mystring,2); echo $arr[0];. Eu sou incapaz de obter a primeira seqüência de caracteres em uma declaração em si - echo explode('/',$mystring,2)[0];. Como explodir retorna uma matriz, eu deveria conseguir fazer isso certo? Mas eu recebo um erro. Alguma sugestão?

1
Php não gosta de você indexar em valores de retorno de funções.
Gnud 20/12/2009

3
ah OK. teria sido bom se fosse possível.

36
explode() + [0]é uma maneira longa de escreverstrtok($string, "/")
mario

5
a propósito, você pode explodir ("/", $ string, 2) [0] no php 5.5
billynoah 24/14

292

A solução mais eficiente é a strtokfunção:

strtok($mystring, '/')

Por exemplo:

$mystring = 'home/cat1/subcat2/';
$first = strtok($mystring, '/');
echo $first; // home

e

$mystring = 'home';
$first = strtok($mystring, '/');
echo $first; // home

25
Isso também é cerca de 40% mais rápido que a current-explodesolução. (Não que eu usá-lo tantas vezes que importa.)
Towr

5
Isso é elegante e rápido - deve ser a resposta aceita.
Kosta Kontos

5
Essa deve ser a resposta exceto. Definitivamente mais rápido e mais ciclos de memória e CPU eficientes do que qualquer uma das explodesoluções fornecidas.
Shivam Maheshwari

O problema com strtoké first/secondretornará, firstmas /secondretornará em secondvez de uma sequência vazia.
precisa saber é o seguinte

Além do meu comentário acima: O comportamento quando uma parte vazia foi encontrada mudou com o PHP 4.1.0. O comportamento antigo retornou uma cadeia vazia, enquanto a nova, correta, o comportamento simplesmente pula a parte da string
rybo111

95
$first = explode("/", $string)[0];

2
elegante, mas não muito eficiente no tempo do computador. Mas nos dias de hoje as pessoas não se importam muito mais sobre os ciclos de CPU minutos
Dennis

13

Que tal isso:

substr($mystring.'/', 0, strpos($mystring, '/'))

Basta adicionar um '/' ao final do mystring para ter certeza de que há pelo menos um;)


Você pode apenas verificar se há uma barra na string antes de fazer isso. Enfim, é a solução mais simples.
Guilherme Sampaio

12

Versão de uma linha da resposta aceita:

$out=explode("/", $mystring, 2)[0];

Deve funcionar no php 5.4+


1
Diferente do abaixo, o "2" limita o número de itens da matriz que ele cria. Bem pensado.
Ben em CA

9

Este é provavelmente o exemplo mais curto que me ocorreu:

list($first) = explode("/", $mystring);

1) list()atribuirá automaticamente a string até "/"que o delimitador seja encontrado
2) se o delimitador "/"não for encontrado, a string inteira será atribuída

... e se você ficar realmente obcecado com desempenho, poderá adicionar um parâmetro extra para explodir, o explode("/", $mystring, 2)que limita o máximo dos elementos retornados.


2
Eu gosto dessa abordagem. Salva criando um array desnecessário. E strtok()é inseguro.
precisa saber é o seguinte

1
@ rybo111: O que é inseguro strtok()?
Hakre

@ rybo111 Eu ecoo o sentimento de hakre; o que torna strtok()inseguro?
Doktor J

@hakre Veja minhas respostas à resposta de jmarceli. Pode causar comportamento inesperado, dependendo da versão do PHP.
rybo111

php 4.1.0 - rly?
hakre

8

Tarde e melhor que nunca. O php tem uma função predefinida para isso. aqui está esse bom caminho.

strstr

se você deseja obter a peça antes da partida, basta definir before_needle (terceiro parâmetro) como true http://php.net/manual/en/function.strstr.php

function not_strtok($string, $delimiter)
{    
    $buffer = strstr($string, $delimiter, true);

    if (false === $buffer) {
        return $string;
    }

    return $buffer;
}

var_dump(
    not_strtok('st/art/page', '/')
);

Não é seguro usá-lo se você não tiver certeza de que a agulha existe na corda.
fooquency

@fooquency - Verdadeiro, mas você sempre pode adicionar o caractere no final da string que está verificando, apenas para ter certeza.
21419 MikeSchinkel

Obrigado. Meus testes mostraram que strstré um pouco mais rápido que strtok. Eu irei com o primeiro.
Ian Y.

5

A função strstr () no PHP 5.3 deve fazer este trabalho. No entanto, o terceiro parâmetro deve ser definido como true.

Mas se você não estiver usando o 5.3, a função abaixo deve funcionar com precisão:

function strbstr( $str, $char, $start=0 ){
    if ( isset($str[ $start ]) && $str[$start]!=$char ){
        return $str[$start].strbstr( $str, $char, $start+1 );
    }
}

Eu ainda não testei, mas isso deve funcionar muito bem .. E é bem rápido também


3
+1 para strstr(), mas lembre-se de que ele retornará falsese a sequência não contiver $needle, portanto, as explode()soluções acima são mais adequadas nesse caso.
24413 Benjamin

3

Você pode criar uma função auxiliar para cuidar disso:

/**
 * Return string before needle if it exists.
 *
 * @param string $str
 * @param mixed $needle
 * @return string
 */
function str_before($str, $needle)
{
    $pos = strpos($str, $needle);

    return ($pos !== false) ? substr($str, 0, $pos) : $str;
}

Aqui está um caso de uso:

$sing = 'My name is Luka. I live on the second floor.';

echo str_before($sing, '.'); // My name is Luka

3

Você pode tentar usar uma regex como esta:

$s = preg_replace('|/.*$|', '', $s);

às vezes, porém, a regex é mais lenta; portanto, se o desempenho é um problema, faça o benchmark corretamente e use outra alternativa com substrings, se for mais adequado para você.


2
O Regex provavelmente também é um exagero, mas como eu digo o mesmo explode, seria interessante ver o que é mais rápido.
precisa saber é

1
não há absolutamente nada de errado com isso e não consigo pensar por que mereceria 2 votos negativos. Eu pessoalmente não usaria regex, mas certamente não está errado.
Billynoah #

2

Usar currentem explodefacilitaria o processo.

 $str = current(explode("/", $str, 2));

0
$string="kalion/home/public_html";

$newstring=( stristr($string,"/")==FALSE ) ? $string : substr($string,0,stripos($string,"/"));

0

Você também pode usar esta solução de uma linha

list($substring) = explode("/", $string);

-1

Eu acho que isso deve funcionar?

substr($mystring, 0, (($pos = (strpos($mystring, '/') !== false)) ? $pos : strlen($mystring)));

Sua função sempre retornará o primeiro caractere porque você está fazendo (strpos ($ mystring, '/')! == false) antes de atribuí-lo a $ pos, você precisa fazer um ((($ pos = strpos ($ firstColumnName, '_'))! == false). Esse seria o liner que o cara que postou a pergunta está procurando.
22615 Mihai P.

-1

por que não usar:

function getwhatiwant($s)
{
    $delimiter='/';
    $x=strstr($s,$delimiter,true);
    return ($x?$x:$s);
}

OU:

   function getwhatiwant($s)
   {
       $delimiter='/';
       $t=explode($delimiter, $s);
       return ($t[1]?$t[0]:$s);
   }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.