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?


fonte
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.

gnud
fonte
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
jmarceli
fonte
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];
AndyBrandy
fonte
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;)

IRCF
fonte
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+

glifo
fonte
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.

Pavlovich
fonte
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', '/')
);
aimme
fonte
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

Ronald
fonte
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
Toby Speight
fonte
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ê.

t00ny
fonte
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));
user1518659
fonte
0
$string="kalion/home/public_html";

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

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

list($substring) = explode("/", $string);
Mas
fonte
-1

Eu acho que isso deve funcionar?

substr($mystring, 0, (($pos = (strpos($mystring, '/') !== false)) ? $pos : strlen($mystring)));
Franz
fonte
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);
   }
user1123382
fonte