Estrazione di sottostringa PHP. Ottieni la stringa prima del primo '/' o dell'intera stringa


170

Sto cercando di estrarre una sottostringa. Ho bisogno di aiuto per farlo in PHP.

Ecco alcune stringhe di esempio con cui sto lavorando e i risultati di cui ho bisogno:

home/cat1/subcat2 => home

test/cat2 => test

startpage => startpage

Voglio ottenere la stringa fino alla prima /, ma se non /è presente, ottenere l'intera stringa.

Provai,

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

Penso che dica: ottenere la posizione di /e quindi ottenere la sottostringa dalla posizione 0 a quella posizione.

Non so come gestire il caso in cui non esiste /, senza rendere l'affermazione troppo grande.

C'è un modo per gestire quel caso anche senza rendere l'istruzione PHP troppo complessa?


1
Potresti trovare s($str)->beforeFirst('/')utile, come si trova in questa libreria autonoma .
Caw

Risposte:


261

Uso explode()

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

In questo caso, sto usando il limitparametro in explodemodo che php non esegua la scansione della stringa più del necessario.


2
+1 Grazie per la risposta. Ha funzionato :) Ma una domanda. Sono solo in grado di fare questo -> $arr = explode('/',$mystring,2); echo $arr[0];. Non riesco a ottenere la prima stringa in una stessa istruzione - echo explode('/',$mystring,2)[0];. Dato che esplode restituisce un array, dovrei essere in grado di farlo bene? Ma ricevo un errore. Eventuali suggerimenti?

1
A Php non piace che tu indicizzi i valori restituiti dalle funzioni.
gnud,

3
Oh. va bene. sarebbe stato carino se fosse stato possibile.

36
explode() + [0]è un modo prolisso per scriverestrtok($string, "/")
mario

5
a proposito, puoi fare esplodere ("/", $ string, 2) [0] in php 5.5
billynoah

293

La soluzione più efficiente è la strtokfunzione:

strtok($mystring, '/')

Per esempio:

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

e

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

25
Anche questo è circa il 40% più veloce della current-explodesoluzione. (Non che lo usi così spesso che conta.)
tra il

5
Questo è elegante e veloce - dovrebbe essere la risposta accettata.
Kosta Kontos,

5
Questa dovrebbe essere la risposta esclusa. Decisamente più veloce e più cicli di memoria e CPU efficienti rispetto a qualsiasi delle explodesoluzioni fornite.
Shivam Maheshwari,

Il problema con strtokIS first/secondtornerà firstma /secondrestituirà secondpiuttosto che una stringa vuota.
Rybo111,

A seguito del mio commento sopra: il comportamento quando è stata trovata una parte vuota è cambiato con PHP 4.1.0. Il vecchio comportamento restituiva una stringa vuota, mentre il nuovo comportamento corretto salta semplicemente la parte della stringa
rybo111,

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

2
elegante, ma non molto efficiente nel tempo del computer. Ma oggigiorno la gente non si preoccupa più dei minuti cicli della CPU
Dennis,

13

Che dire di questo :

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

Aggiungi semplicemente un '/' alla fine del mystring in modo da essere sicuro che ce ne sia almeno uno;)


Puoi semplicemente controllare se c'è una barra nella stringa prima di farlo. Comunque, è la soluzione più semplice.
Guilherme Sampaio,

12

Versione a una riga della risposta accettata:

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

Dovrebbe funzionare in php 5.4+


1
A differenza di quello sotto, "2" limita il numero di elementi dell'array che crea. Pensare bene.
Ben in California,

9

Questo è probabilmente l'esempio più breve che mi è venuto in mente:

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

1) list()assegnerà automaticamente la stringa fino a "/"quando non viene trovato il delimitatore
2) se il delimitatore "/"non viene trovato, verrà assegnata l'intera stringa

... e se sei veramente ossessionato dalle prestazioni, puoi aggiungere un parametro extra per esplodere explode("/", $mystring, 2)che limita il massimo degli elementi restituiti.


2
Mi piace questo approccio. Salva facendo un array inutile. Ed strtok()è pericoloso.
Rybo111,

1
@ rybo111: cosa non è sicuro strtok()?
Hacre,

@ rybo111 Iho l'emozione di hakre; cosa rende strtok()insicuro?
Doktor J,

@hakre Vedi le mie risposte alla risposta di Jmarceli. Può causare comportamenti imprevisti a seconda della versione di PHP.
Rybo111,

php 4.1.0 - rly?
hakre,

8

Meglio tardi che mai. php ha una funzione predefinita per questo. ecco quel buon modo.

strstr

se vuoi ottenere la parte prima della partita, imposta prima before_needle (3 ° parametro) su 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', '/')
);

Questo non è sicuro da usare se non si è sicuri che l'ago esista nella corda.
Fooquency

@fooquency - Vero, ma puoi sempre aggiungere il carattere alla fine della stringa che stai controllando, per essere sicuro.
MikeSchinkel,

Grazie. I miei test hanno dimostrato che strstrè leggermente più veloce di strtok. Andrò con il primo.
Ian Y.

5

La funzione strstr () in PHP 5.3 dovrebbe fare questo lavoro. Il terzo parametro dovrebbe essere impostato su true ..

Ma se non si utilizza 5.3, la funzione seguente dovrebbe funzionare in modo accurato:

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

Non l'ho ancora provato, ma dovrebbe funzionare bene .. Ed è anche abbastanza veloce


3
+1 per strstr(), ma tieni presente che restituisce falsese la stringa non contiene $needle, quindi le explode()soluzioni sopra indicate si adattano meglio in questo caso.
Benjamin,

3

È possibile creare una funzione di supporto per occuparsi di questo:

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

Ecco un caso d'uso:

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

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

3

Puoi provare a usare un regex come questo:

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

a volte, regex è più lento, quindi se le prestazioni sono un problema, assicurati di confrontarlo correttamente e usa un'altra alternativa con sottostringhe se è più adatto a te.


2
Probabilmente anche Regex è eccessivo, ma dal momento che dico la stessa explodecosa sarebbe interessante vedere quale è più veloce.
rvighne,

1
non c'è assolutamente nulla di sbagliato in questo e non riesco a pensare al motivo per cui meriterebbe 2 downvotes. Personalmente non userei regex ma certamente non è sbagliato.
Billynoah,

2

L'uso di currenton explodefaciliterebbe il processo.

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

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

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

0

Puoi anche usare questa soluzione a una riga

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

-1

Penso che dovrebbe funzionare?

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

La tua funzione restituirà sempre il primo carattere perché stai facendo (strpos ($ mystring, '/')! == false) prima di assegnarlo a $ pos, devi fare un (($ pos = strpos ($ firstColumnName, '_'))! == false). Questa sarebbe la 1 linea che il ragazzo che ha pubblicato la domanda sta cercando.
Mihai P.

-1

perché non usare:

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

O:

   function getwhatiwant($s)
   {
       $delimiter='/';
       $t=explode($delimiter, $s);
       return ($t[1]?$t[0]:$s);
   }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.