การแยกสตริงย่อย PHP รับสายก่อน '/' แรกหรือสตริงทั้งหมด


170

ฉันพยายามแยกสตริงย่อย ฉันต้องการความช่วยเหลือเกี่ยวกับการทำมันใน PHP

นี่คือตัวอย่างสตริงที่ฉันใช้ด้วยและผลลัพธ์ที่ต้องการ:

home/cat1/subcat2 => home

test/cat2 => test

startpage => startpage

ฉันต้องการรับสายจนถึงก่อน/แต่ถ้าไม่มี/อยู่รับสายทั้งหมด

ฉันเหนื่อย,

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

ฉันคิดว่ามันบอกว่า - ได้รับตำแหน่งของ/แล้วได้รับ substring จากตำแหน่ง 0 ไปที่ตำแหน่ง

ผมไม่ทราบวิธีการจัดการกรณีที่ไม่มีการ/โดยไม่ทำให้คำสั่งที่มีขนาดใหญ่เกินไป

มีวิธีจัดการกับกรณีนั้นโดยไม่ทำให้คำสั่ง PHP ซับซ้อนเกินไปหรือไม่


1
คุณอาจพบว่ามีs($str)->beforeFirst('/')ประโยชน์ดังที่พบในไลบรารีแบบสแตนด์อโลนนี้
caw

คำตอบ:


261

ใช้ explode()

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

ในกรณีนี้ฉันใช้limitพารามิเตอร์เพื่อexplodeให้ php ไม่สแกนสตริงเกินกว่าที่จำเป็น


2
+1 ขอบคุณสำหรับคำตอบ มันได้ผล :) แต่คำถามเดียว ฉันเป็นเพียงสามารถทำเช่นนี้ $arr = explode('/',$mystring,2); echo $arr[0];-> ฉันไม่สามารถที่จะได้รับสายแรกในงบหนึ่งตัวเอง echo explode('/',$mystring,2)[0];- เนื่องจาก explode ส่งคืนอาร์เรย์ฉันควรทำถูกไหม แต่ฉันได้รับข้อผิดพลาด ข้อเสนอแนะใด ๆ

1
php ไม่ชอบให้คุณจัดทำดัชนีเป็นค่าตอบแทนจากฟังก์ชั่น
gnud

3
โอ้ ตกลง. คงจะดีถ้าเป็นไปได้

36
explode() + [0]เป็นวิธีการเขียนที่ยืดยาวstrtok($string, "/")
mario

5
โดยวิธีการที่คุณสามารถทำระเบิด ("/", $ string, 2) [0] ใน php 5.5
billynoah

293

มีประสิทธิภาพมากที่สุดวิธีการแก้ปัญหาคือstrtokฟังก์ชั่น:

strtok($mystring, '/')

ตัวอย่างเช่น:

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

และ

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

25
นี่ยังเร็วกว่าcurrent-explodeโซลูชันประมาณ 40% (ไม่ใช่ว่าฉันจะใช้มันบ่อยเท่าที่มันสำคัญ)
14:30

5
นี่คือความสวยงามและรวดเร็ว - ควรเป็นคำตอบที่ได้รับการยอมรับ
Kosta Kontos

5
นี่ควรเป็นคำตอบที่ได้รับการยกเว้น หน่วยความจำและซีพียูและวงจรที่มีประสิทธิภาพเร็วขึ้นอย่างแน่นอนและมีประสิทธิภาพexplodeมากขึ้น
Shivam Maheshwari

ปัญหากับการstrtokมีที่first/secondจะกลับมาfirstแต่/secondจะกลับมาsecondมากกว่าสตริงที่ว่างเปล่า
rybo111

นอกจากความคิดเห็นข้างบนของฉัน: พฤติกรรมเมื่อพบส่วนที่ว่างเปล่าถูกเปลี่ยนด้วย PHP 4.1.0 พฤติกรรมเก่าส่งคืนสตริงว่างเปล่าในขณะที่พฤติกรรมใหม่ถูกต้องเพียงข้ามส่วนของสตริง
rybo111

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

2
สง่างาม แต่ไม่ค่อยมีประสิทธิภาพในเวลาที่ใช้คอมพิวเตอร์ แต่ทุกวันนี้ผู้คนไม่สนใจอะไรอีกต่อไปเกี่ยวกับรอบการทำงานซีพียูนาที
เดนนิส

13

เกี่ยวกับสิ่งนี้:

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

เพียงเพิ่ม '/' ที่ส่วนท้ายของ mystring เพื่อให้คุณมั่นใจได้ว่ามีอย่างน้อยหนึ่ง;)


คุณสามารถตรวจสอบว่ามีหนึ่งเครื่องหมายทับในสตริงก่อนทำสิ่งนี้หรือไม่ อย่างไรก็ตามมันเป็นทางออกที่ง่ายที่สุด
Guilherme Sampaio

12

คำตอบที่ยอมรับในเวอร์ชันหนึ่งบรรทัด:

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

ควรทำงานใน php 5.4+


1
ไม่เหมือนกับรายการด้านล่าง "2" จำกัด จำนวนรายการอาร์เรย์ที่สร้าง ความคิดที่ดี.
เบ็นใน CA

9

นี่อาจเป็นตัวอย่างที่สั้นที่สุดที่อยู่ในใจของฉัน:

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

1) list()จะกำหนดสตริงโดยอัตโนมัติจนกว่า"/"จะพบตัวคั่น
2) หาก"/"ไม่พบตัวคั่นแล้วสตริงทั้งหมดจะถูกกำหนด

... และหากคุณหมกมุ่นอยู่กับประสิทธิภาพจริงๆคุณอาจเพิ่มพารามิเตอร์พิเศษเพื่อขยายexplode("/", $mystring, 2)ซึ่ง จำกัด จำนวนองค์ประกอบที่ส่งคืนได้สูงสุด


2
ฉันชอบวิธีนี้ ช่วยประหยัดอาร์เรย์ที่ไม่จำเป็น และstrtok()ไม่ปลอดภัย
rybo111

1
@ rybo111: ไม่ปลอดภัยเกี่ยวกับstrtok()อะไร
hakre

@ rybo111 ฉันสะท้อนความเชื่อมั่นของ hakre; อะไรทำให้strtok()ไม่ปลอดภัย
Doktor J

@hakre ดูคำตอบของฉันสำหรับคำตอบของ jmarceli มันอาจทำให้เกิดพฤติกรรมที่ไม่คาดคิดขึ้นอยู่กับเวอร์ชันของ PHP
rybo111

PHP 4.1.0 - rly?
hakre

8

สายดีกว่าไม่เคย php มีฟังก์ชันที่กำหนดไว้ล่วงหน้าสำหรับสิ่งนั้น นี่เป็นวิธีที่ดี

strstr

หากคุณต้องการได้รับส่วนก่อนการแข่งขันเพียงแค่ตั้งค่าbefore_needle (พารามิเตอร์ที่ 3) เป็น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', '/')
);

วิธีนี้ไม่ปลอดภัยหากคุณไม่แน่ใจว่ามีเข็มอยู่ในสายหรือไม่
fooquency

@fooquency - จริง แต่คุณสามารถเพิ่มอักขระไปยังจุดสิ้นสุดของสตริงที่คุณกำลังตรวจสอบอยู่เสมอเพื่อให้แน่ใจ
MikeSchinkel

ขอบคุณ การทดสอบแสดงให้เห็นว่าฉันจะเร็วกว่าเล็กน้อยstrstr strtokฉันจะไปกับอดีต
Ian Y.

5

ฟังก์ชัน strstr () ใน PHP 5.3 ควรทำงานนี้ .. พารามิเตอร์ที่สามอย่างไรก็ตามควรตั้งค่าเป็นจริง ..

แต่ถ้าคุณไม่ได้ใช้ 5.3 ดังนั้นฟังก์ชั่นด้านล่างควรทำงานอย่างถูกต้อง:

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

ฉันยังไม่ได้ทดสอบ แต่มันควรจะใช้ได้ดีและมันก็ค่อนข้างเร็วเช่นกัน


3
+1 สำหรับstrstr()แต่โปรดทราบว่ามันจะส่งคืนfalseหากสตริงไม่มี$needleดังนั้นการexplode()แก้ปัญหาข้างต้นจะเหมาะสมกว่าในกรณีนี้
เบนจามิน

3

คุณสามารถสร้างฟังก์ชั่นตัวช่วยเพื่อดูแลสิ่งต่อไปนี้:

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

นี่คือกรณีการใช้งาน:

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

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

3

คุณสามารถลองใช้ regex ดังนี้:

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

บางครั้ง regex จะช้ากว่าดังนั้นหากประสิทธิภาพเป็นปัญหาตรวจสอบให้แน่ใจว่าได้ทำการเปรียบเทียบอย่างถูกต้องและใช้ทางเลือกอื่นกับสตริงย่อยถ้ามันเหมาะกว่าสำหรับคุณ


2
Regex ก็อาจ overkill เกินไป แต่เนื่องจากฉันพูดเหมือนกันเกี่ยวกับexplodeมันจะน่าสนใจเพื่อดูว่าเร็วขึ้น
rvighne

1
ไม่มีอะไรผิดปกติกับสิ่งนี้และฉันไม่สามารถคิดได้ว่าทำไมมันจึงสมควรได้รับ 2 downvotes โดยส่วนตัวฉันจะไม่ใช้ regex แต่ก็ไม่ผิดแน่นอน
billynoah



0

คุณยังสามารถใช้โซลูชันเดียวนี้ได้

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

-1

ฉันคิดว่ามันน่าจะใช้ได้เหรอ

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

ฟังก์ชั่นของคุณจะส่งคืนอักขระตัวแรกเสมอเพราะคุณกำลังทำอยู่ (strpos ($ mystring, '/')! == false) ก่อนที่คุณจะกำหนดให้กับ $ pos คุณต้องทำ (($ pos = strpos ($ firstColumnName, '_'))! == false) นี่จะเป็น 1 สายการบินคนที่โพสต์คำถามที่กำลังมองหา
หมดเวลา P.

-1

ทำไมไม่ใช้:

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

หรือ:

   function getwhatiwant($s)
   {
       $delimiter='/';
       $t=explode($delimiter, $s);
       return ($t[1]?$t[0]:$s);
   }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.