Extraction de sous-chaînes PHP. Récupère la chaîne avant le premier «/» ou la chaîne entière


170

J'essaye d'extraire une sous-chaîne. J'ai besoin d'aide pour le faire en PHP.

Voici quelques exemples de chaînes avec lesquelles je travaille et les résultats dont j'ai besoin:

home/cat1/subcat2 => home

test/cat2 => test

startpage => startpage

Je veux obtenir la chaîne jusqu'au premier /, mais si aucun /n'est présent, récupère la chaîne entière.

J'ai essayé,

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

Je pense que cela dit - obtenir la position de /, puis obtenir la sous-chaîne de la position 0 à cette position.

Je ne sais pas comment gérer le cas où il n'y en a pas /, sans rendre la déclaration trop grande.

Existe-t-il un moyen de gérer ce cas également sans rendre l'instruction PHP trop complexe?


1
Vous pourriez trouver s($str)->beforeFirst('/')utile, comme trouvé dans cette bibliothèque autonome .
— caw

Réponses:


261

Utilisation explode()

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

Dans ce cas, j'utilise le limitparamètre to explodeafin que php ne scanne pas la chaîne plus que ce qui est nécessaire.


2
+1 Merci pour la réponse. Cela a fonctionné :) Mais une question. Je ne peux le faire que -> $arr = explode('/',$mystring,2); echo $arr[0];. Je ne parviens pas à obtenir la première chaîne dans une instruction elle-même - echo explode('/',$mystring,2)[0];. Puisque exploser renvoie un tableau, je devrais être capable de le faire correctement? Mais j'obtiens une erreur. Aucune suggestion?

1
Php n'aime pas que vous indexiez les valeurs de retour des fonctions.
— gnud

3
Oh. d'accord. aurait été bien si c'était possible.

36
explode() + [0]est une façon fastidieuse d'écrirestrtok($string, "/")
— mario

5
en passant, vous pouvez faire exploser ("/", $ string, 2) [0] en php 5.5
— billynoah

293

La solution la plus efficace est la strtokfonction:

strtok($mystring, '/')

Par exemple:

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

et

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

25
C'est également environ 40% plus rapide que la current-explodesolution. (Non pas que je l'utilise si souvent que cela compte.)
— vers

5
C'est élégant et rapide - devrait être la réponse acceptée.
— Kosta Kontos

5
Cela devrait être la réponse exceptée. Définitivement plus rapide et plus de cycles de mémoire et de processeur efficaces que toutes les explodesolutions proposées.
— Shivam Maheshwari

Le problème avec strtokest first/secondretournera firstmais /secondretournera secondplutôt qu'une chaîne vide.
— rybo111 le

Suite à mon commentaire ci-dessus: le comportement lorsqu'une partie vide a été trouvée a changé avec PHP 4.1.0. L'ancien comportement a renvoyé une chaîne vide, tandis que le nouveau comportement correct ignore simplement la partie de la chaîne
— rybo111

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

2
élégant, mais pas très efficace en temps informatique. Mais ces jours-ci, les gens ne se soucient plus beaucoup des cycles de processeur minute
— Dennis

13

Et ça :

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

Ajoutez simplement un '/' à la fin de mystring pour être sûr qu'il y en a au moins un;)


Vous pouvez simplement vérifier s'il y a une barre oblique dans la chaîne avant de faire cela. Quoi qu'il en soit, c'est la solution la plus simple.
— Guilherme Sampaio

12

Version en une ligne de la réponse acceptée:

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

Devrait fonctionner en PHP 5.4+


1
Contrairement à celui ci-dessous, le "2" limite le nombre d'éléments de tableau qu'il crée. Bien pensé.
— Ben en Californie

9

C'est probablement l'exemple le plus court qui m'est venu à l'esprit:

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

1) list()attribuera automatiquement la chaîne jusqu'à ce "/"que le délimiteur soit trouvé
2) si le délimiteur "/"n'est pas trouvé, la chaîne entière sera affectée

... et si vous êtes vraiment obsédé par les performances, vous pouvez ajouter un paramètre supplémentaire pour exploser explode("/", $mystring, 2)qui limite le maximum des éléments retournés.


2
J'aime cette approche. Enregistre la création d'un tableau inutile. Et strtok()c'est dangereux.
— rybo111 le

1
@ rybo111: Qu'est-ce qui est dangereux strtok()?
— hakre

@ rybo111 Je fais écho au sentiment de Hakre; qu'est-ce qui rend strtok()dangereux?
— Doktor J

@hakre Voir mes réponses à la réponse de jmarceli. Cela peut provoquer un comportement inattendu selon la version de PHP.
— rybo111 le

php 4.1.0 - rly?
— hakre

8

Mieux vaut tard que jamais. php a une fonction prédéfinie pour cela. voici ce bon moyen.

strstr

si vous voulez obtenir la partie avant la correspondance, définissez simplement before_needle (3e paramètre) sur 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', '/')
);

Ce n'est pas sûr à utiliser si vous ne pouvez pas être sûr que l'aiguille existe dans la chaîne.
— fréquence du

@fooquency - Vrai, mais vous pouvez toujours ajouter le caractère à la fin de la chaîne que vous vérifiez, juste pour être sûr.
— MikeSchinkel

Merci. Mes tests ont montré que strstrc'est légèrement plus rapide que strtok. J'irai avec le premier.
— Ian Y.23

5

La fonction strstr () de PHP 5.3 devrait faire ce travail. Le troisième paramètre doit cependant être défini sur true.

Mais si vous n'utilisez pas 5.3, la fonction ci-dessous devrait fonctionner correctement:

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

Cependant, je ne l'ai pas testé, mais cela devrait très bien fonctionner. Et c'est assez rapide aussi


3
+1 pour strstr(), mais sachez qu'il retourne falsesi la chaîne ne contient pas $needle, donc les explode()solutions ci-dessus conviennent mieux dans ce cas.
— Benjamin

3

Vous pouvez créer une fonction d'assistance pour vous en occuper:

/**
 * 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;
}

Voici un cas d'utilisation:

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

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

3

Vous pouvez essayer d'utiliser une expression régulière comme celle-ci:

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

parfois, les expressions régulières sont plus lentes, donc si les performances sont un problème, assurez-vous de les comparer correctement et utilisez une autre alternative avec des sous-chaînes si cela vous convient mieux.


2
Regex est probablement exagéré aussi, mais comme je dis la même chose, explodeil serait intéressant de voir lequel est le plus rapide.
— rvighne

1
il n'y a absolument rien de mal à cela et je ne vois pas pourquoi cela mériterait 2 votes négatifs. Personnellement, je n'utiliserais pas regex mais ce n'est certainement pas faux.
— billynoah le

2

Utiliser currentsur explodefaciliterait le processus.

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

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

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

0

Vous pouvez également utiliser cette solution en une ligne

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

-1

Je pense que cela devrait fonctionner?

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

Votre fonction retournera toujours le premier caractère car vous faites (strpos ($ mystring, '/')! == false) avant de l'affecter à $ pos, vous devez faire un (($ pos = strpos ($ firstColumnName, '_'))! == false). Ce serait la 1 doublure recherchée par le type qui a posé la question.
— Mihai P.

-1

pourquoi ne pas utiliser:

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);
   }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.