Wyodrębnianie podciągów PHP. Pobierz ciąg przed pierwszym „/” lub cały ciąg


170

Próbuję wyodrębnić podciąg. Potrzebuję pomocy przy zrobieniu tego w PHP.

Oto kilka przykładowych ciągów, z którymi pracuję, i potrzebnych mi wyników:

home/cat1/subcat2 => home

test/cat2 => test

startpage => startpage

Chcę uzyskać ciąg do pierwszego /, ale jeśli nie /ma, zdobądź cały ciąg.

Próbowałem,

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

Myślę, że mówi - uzyskaj pozycję, /a następnie pobierz podciąg z pozycji 0 do tej pozycji.

Nie wiem, jak sobie poradzić z przypadkiem, w którym nie ma /, bez zbytniego stwierdzenia.

Czy istnieje sposób na obsłużenie tego przypadku bez zbytniego komplikowania instrukcji PHP?


1
Może okazać się s($str)->beforeFirst('/')pomocny, co znajdziesz w tej samodzielnej bibliotece .
krakaj

Odpowiedzi:


261

Posługiwać się explode()

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

W tym przypadku używam limitparametru, aby explodephp nie skanował ciągu więcej niż jest to potrzebne.


2
+1 Dzięki za odpowiedź. Udało się :) Ale jedno pytanie. Jestem w stanie to zrobić tylko -> $arr = explode('/',$mystring,2); echo $arr[0];. Nie mogę uzyskać pierwszego ciągu w jednym oświadczeniu - echo explode('/',$mystring,2)[0];. Ponieważ eksplodowanie zwraca tablicę, powinienem być w stanie to zrobić, prawda? Ale pojawia się błąd. Jakieś sugestie?

1
Php nie lubi, gdy indeksujesz wartości zwracane przez funkcje.
gnud

3
O. w porządku. byłoby miło, gdyby to było możliwe.

36
explode() + [0]to rozwlekły sposób pisaniastrtok($string, "/")
mario

5
przy okazji, możesz eksplodować ("/", $ string, 2) [0] w php 5.5
billynoah

293

Najskuteczniejszym rozwiązaniem jest strtokfunkcja:

strtok($mystring, '/')

Na przykład:

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

i

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

25
Jest to również około 40% szybsze niż current-exploderozwiązanie. (Nie to, że używam go tak często, że ma to znaczenie.)
około

5
To eleganckie i szybkie - powinna być akceptowana odpowiedź.
Kosta Kontos

5
To powinna być wyjątkowa odpowiedź. Zdecydowanie szybsze i wydajniejsze cykle pamięci i procesora niż którekolwiek z podanych exploderozwiązań.
Shivam Maheshwari,

Problem z strtokto first/secondzwróci, firstale /secondzwróci secondzamiast pustego ciągu.
rybo111

W nawiązaniu do mojego powyższego komentarza: Zachowanie po znalezieniu pustej części zmieniło się w PHP 4.1.0. Stare zachowanie zwróciło pusty ciąg, podczas gdy nowe, poprawne zachowanie po prostu pomija część ciągu
rybo111

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

2
eleganckie, ale niezbyt wydajne w czasie pracy komputera. Ale w dzisiejszych czasach ludzie nie przejmują się już minimalnymi cyklami procesora
Dennis

13

A co z tym :

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

Po prostu dodaj „/” na końcu mystringu, aby mieć pewność, że jest co najmniej jeden;)


Możesz po prostu sprawdzić, czy w ciągu znaków jest jeden ukośnik, zanim to zrobisz. Zresztą to najprostsze rozwiązanie.
Guilherme Sampaio

12

Jednowierszowa wersja zaakceptowanej odpowiedzi:

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

Powinien działać w php 5.4+


1
W przeciwieństwie do poniższego „2” ogranicza liczbę tworzonych elementów tablicy. Dobre myślenie.
Ben w Kalifornii

9

To chyba najkrótszy przykład, jaki przyszedł mi do głowy:

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

1) list()automatycznie przypisuje ciąg do momentu "/"znalezienia separatora
2) jeśli separator "/"nie zostanie znaleziony, zostanie przypisany cały ciąg

... a jeśli masz obsesję na punkcie wydajności, możesz dodać dodatkowy parametr, aby eksplodować, explode("/", $mystring, 2)który ogranicza maksymalną liczbę zwracanych elementów.


2
Podoba mi się to podejście. Oszczędza tworzenie niepotrzebnej tablicy. I strtok()jest niebezpieczny.
rybo111

1
@ rybo111: Co jest niebezpieczne strtok()?
hakre

@ rybo111 Powtarzam sentyment hakre; co czyni strtok()niebezpiecznym?
Doktor J

@hakre Zobacz moje odpowiedzi na odpowiedź jmarceli. Może to spowodować nieoczekiwane zachowanie w zależności od wersji PHP.
rybo111

php 4.1.0 - rly?
hakre

8

Lepiej późno niż wcale. php ma do tego predefiniowaną funkcję. oto dobry sposób.

strstr

jeśli chcesz otrzymać część przed dopasowaniem, po prostu ustaw before_needle (trzeci parametr) na true http://php.net/manual/en/function.str.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', '/')
);

Nie jest to bezpieczne w użyciu, jeśli nie masz pewności, że igła znajduje się w sznurku.
częstotliwość

@fooquency - prawda, ale zawsze możesz dodać znak na końcu sprawdzanego ciągu, dla pewności.
MikeSchinkel,

Dzięki. Moje testy wykazały, że strstrjest nieco szybszy niż strtok. Pójdę z tym pierwszym.
Ian Y.

5

Funkcja strstr () w PHP 5.3 powinna wykonać to zadanie. Jednak trzeci parametr powinien być ustawiony na wartość true ..

Ale jeśli nie używasz 5.3, poniższa funkcja powinna działać dokładnie:

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

Nie testowałem tego, ale to powinno działać dobrze ... I jest też całkiem szybkie


3
+1 dla strstr(), ale pamiętaj, że zwraca, falsejeśli ciąg nie zawiera $needle, dlatego explode()powyższe rozwiązania są lepiej dopasowane w tym przypadku.
Benjamin

3

Możesz stworzyć funkcję pomocniczą, aby się tym zająć:

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

Oto przykład użycia:

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

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

3

Możesz spróbować użyć wyrażenia regularnego w ten sposób:

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

czasami wyrażenia regularne są jednak wolniejsze, więc jeśli problemem jest wydajność, upewnij się, że wykonałeś to poprawnie i użyj innej alternatywy z podciągami, jeśli jest bardziej odpowiednia dla Ciebie.


2
Regex to prawdopodobnie przesada, ale skoro mówię to samo explode, ciekawie byłoby zobaczyć, który jest szybszy.
rvighne

1
nie ma w tym absolutnie nic złego i nie wiem, dlaczego zasługiwałoby na 2 głosy przeciw. Osobiście nie użyłbym wyrażenia regularnego, ale z pewnością nie jest to złe.
billynoah

2

Używanie currentna explodeułatwiłoby ten proces.

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

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

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

0

Możesz także skorzystać z tego rozwiązania jednokreskowego

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

-1

Myślę, że to powinno działać?

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

Twoja funkcja zawsze zwróci pierwszy znak, ponieważ robisz (strpos ($ mystring, '/')! == false) zanim przypiszesz ją do $ pos, musisz zrobić (($ pos = strpos ($ firstColumnName, '_'))! == false). Byłby to pierwszy wkład, którego szuka facet, który opublikował pytanie.
Mihai P.

-1

dlaczego nie użyć:

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

LUB:

   function getwhatiwant($s)
   {
       $delimiter='/';
       $t=explode($delimiter, $s);
       return ($t[1]?$t[0]:$s);
   }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.