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.