PHP alt dize çıkarma. Dizeyi ilk '/' işaretinden veya dizenin tamamından önce alın


170

Bir alt dize ayıklamak çalışıyorum. PHP bunu yapmak için biraz yardıma ihtiyacım var.

Birlikte çalıştığım bazı örnek dizeler ve ihtiyacım olan sonuçlar:

home/cat1/subcat2 => home

test/cat2 => test

startpage => startpage

Ben ilk kadar dize almak istiyorum /, ama hayır varsa /, tüm dize olsun.

Denedim,

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

Bence diyor - pozisyonunu al /ve sonra alt dizeyi 0 konumundan o pozisyona getir .

/İfadeyi çok büyük yapmadan , yok olan davaya nasıl bakacağımı bilmiyorum .

PHP deyimini çok karmaşık hale getirmeden bu durumu ele almanın bir yolu var mı?


Yanıtlar:


261

kullanım explode()

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

Bu durumda, php dizeyi gerekenden daha fazla taramayacak şekilde limitparametresini kullanıyorum explode.


2
+1 Cevabınız için teşekkürler. İşe yaradı :) Ama bir soru. Sadece bunu yapabiliyorum -> $arr = explode('/',$mystring,2); echo $arr[0];. İlk ifadeyi tek bir ifadede alamıyorum - echo explode('/',$mystring,2)[0];. Patlama bir dizi döndürdüğünden, doğru yapmalıyım? Ama bir hata alıyorum. Baska öneri?

1
Php işlevlerden dönüş değerlerine endeksleme gibi değil.
gnud

3
ah. Tamam. mümkünse güzel olurdu.

36
explode() + [0]yazmak için uzun soluklu bir yoldurstrtok($string, "/")
mario

5
Bu arada, php 5.5'te patlayabilir ("/", $ string, 2) [0]
billynoah

293

En verimli bir çözüm strtokişlevi:

strtok($mystring, '/')

Örneğin:

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

ve

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

25
Bu aynı zamanda current-explodeçözeltiden yaklaşık% 40 daha hızlıdır . (Bu kadar sık ​​kullandığım için önemli değil.)
towr

5
Bu zarif ve hızlı - kabul edilen cevap olmalı.
Kosta Kontos

5
Bu istisna cevap olmalıdır. Kesinlikle daha hızlı ve daha fazla bellek ve CPU döngüleri explodeverilen çözümlerden daha verimli .
Shivam Maheshwari

Sorun strtokDİR first/seconddönecektir firstama /seconddönecektir secondboş bir dizeye ziyade.
rybo111

Yukarıdaki yorumuma ek olarak: Boş bir bölüm bulunduğunda davranış PHP 4.1.0 ile değişmiştir. Eski davranış boş bir dize döndürürken, yeni, doğru, davranış sadece dizenin bir bölümünü atlar
rybo111

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

2
zarif, ama bilgisayar zamanında çok verimli değil. Ama bu gün millet artık CPU döngüleri hakkında çok fazla umursamıyor
Dennis

13

Peki buna ne dersin :

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

En azından bir tane olduğundan emin olabilmeniz için gizem sonuna bir '/' eklemeniz yeterlidir;)


Bunu yapmadan önce dizede bir eğik çizgi olup olmadığını kontrol edebilirsiniz. Her neyse, bu en basit çözüm.
Guilherme Sampaio

12

Kabul edilen cevabın tek satırlı versiyonu:

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

Php 5.4+ ile çalışmalı


1
Aşağıdakilerden farklı olarak, "2" oluşturduğu dizi öğelerinin sayısını sınırlar. İyi düşünmek.
CA'daki Ben

9

Bu muhtemelen aklıma gelen en kısa örnek:

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

1) sınırlayıcı list()bulunana kadar otomatik olarak dize atar 2) sınırlayıcı bulunmazsa tüm dize atanır"/"
"/"

... ve performansa gerçekten takıntılı olursanız, patlamak explode("/", $mystring, 2)için döndürülen öğelerin maksimum sınırını aşan ekstra parametre ekleyebilirsiniz .


2
Bu yaklaşımı seviyorum. Gereksiz bir dizi oluşturmayı kaydeder. Ve strtok()güvensiz.
rybo111

1
@ rybo111: Güvensiz nedir strtok()?
hakre

@ rybo111 Hakre'nin hissini yankıyorum; strtok()güvensiz yapan nedir?
Doktor J

@hakre jmarceli'nin cevabına verdiğim cevapları gör. PHP sürümüne bağlı olarak beklenmedik davranışlara neden olabilir.
rybo111

4.1.0 - rly?
hakre

8

Geç kalmak hiç olmadığı kadar iyidir. php bunun için önceden tanımlanmış bir işleve sahiptir. İşte bu iyi yol.

strstr

eşleşmeden önce parçayı almak istiyorsanız, önce before_needle (3. parametre) ayarını 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', '/')
);

İğnenin dizede bulunduğundan emin olamıyorsanız, bu güvenli değildir.
fooquency

@fooquency - Doğru, ancak karakteri kontrol ettiğiniz dizenin sonuna her zaman ekleyebilirsiniz, emin olmak için.
MikeSchinkel

Teşekkürler. Testlerim bunun strstrbiraz daha hızlı olduğunu gösterdi strtok. Birincisi ile gideceğim.
Ian Y.

5

PHP 5.3'teki strstr () işlevi bu işi yapmalıdır. Ancak üçüncü parametre true değerine ayarlanmalıdır.

Ancak 5.3 kullanmıyorsanız, aşağıdaki işlev doğru bir şekilde çalışmalıdır:

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

Yine de test etmedim, ama bu gayet iyi çalışmalı .. Ve oldukça hızlı


3
+1 için strstr(), ancak falsedize içermiyorsa geri döndüğünü unutmayın $needle, bu nedenle explode()yukarıdaki çözümler bu durumda daha iyi bir seçimdir.
Benjamin

3

Bununla ilgilenmek için bir yardımcı işlev oluşturabilirsiniz:

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

İşte bir kullanım örneği:

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

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

3

Bunun gibi bir normal ifade kullanmayı deneyebilirsiniz:

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

bazen regex daha yavaştır, bu nedenle performans bir sorunsa, bunu doğru bir şekilde karşılaştırdığınızdan emin olun ve sizin için daha uygunsa alt dizelerle başka bir alternatif kullanın.


2
Regex muhtemelen aşırıya kaçmış, ama aynı şeyi söylediğimden explodehangisinin daha hızlı olduğunu görmek ilginç olurdu.
rvighne

1
Bu konuda kesinlikle yanlış bir şey yok ve neden 2 downvotes hak edeceğini düşünemiyorum. Şahsen regex kullanmazdım ama kesinlikle yanlış değil.
billynoah

2

Kullanımı currentile ilgili explodeişlemi kolay olacak.

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

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

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

0

Bu tek satırlık çözümü de kullanabilirsiniz

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

-1

Bence bu işe yarıyor mu?

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

$ Pos'a atamadan önce (strpos ($ mystring, '/')! == false) yaptığınız için işleviniz her zaman ilk karakteri döndürecektir, bir (($ pos = strpos ($ firstColumnName, '_'))! == yanlış). Bu soruyu gönderen adam arıyor 1 liner olurdu.
Mihai P.

-1

neden kullanmıyorsunuz:

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

VEYA:

   function getwhatiwant($s)
   {
       $delimiter='/';
       $t=explode($delimiter, $s);
       return ($t[1]?$t[0]:$s);
   }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.