ลบสตริงออกจากจุดเริ่มต้นของสตริง


146

ฉันมีสตริงที่มีลักษณะเช่นนี้:

$str = "bla_string_bla_bla_bla";

ฉันจะลบอันแรกออกได้bla_อย่างไร; แต่ถ้าพบที่จุดเริ่มต้นของสตริงหรือไม่

ด้วยstr_replace()ก็เอาทั้งหมด bla_ของ


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

คำตอบ:


339

รูปแบบธรรมดาโดยไม่มี regex:

$prefix = 'bla_';
$str = 'bla_string_bla_bla_bla';

if (substr($str, 0, strlen($prefix)) == $prefix) {
    $str = substr($str, strlen($prefix));
} 

ใช้เวลา: 0.0369 ms (0.000,036,954 วินาที)

และด้วย:

$prefix = 'bla_';
$str = 'bla_string_bla_bla_bla';
$str = preg_replace('/^' . preg_quote($prefix, '/') . '/', '', $str);

ใช้เวลา: 0.1749 มิลลิวินาที (0.000,174,999 วินาที) ระยะที่ 1 (รวบรวม) และ0.0510 มิลลิวินาที (0.000,051,021 วินาที) หลังจากนั้น

ทำโปรไฟล์บนเซิร์ฟเวอร์ของฉันอย่างชัดเจน


8
ฉันไม่เคยเห็นผู้ประกอบการที่ถูกทารุณกรรมที่ถูกทารุณกรรมอย่างเลวร้ายแบบธรรมดาif(condition) { statement }จะชัดเจนยิ่งขึ้น
Tatu Ulmanen

4
@salathe: ฉันยอมรับคำวิจารณ์ มันเป็นความอยากรู้อยากเห็นส่วนบุคคลเพื่อดูว่าอะไรเร็วที่สุด
Fabio Mora

51
@ ซาเล็มฉันไม่เข้าใจ มีการนำเสนอโซลูชันที่ใช้สำนวนและ regex: การเปรียบเทียบทั้งสองในแง่ของประสิทธิภาพช่วยให้หาคำตอบที่ดีที่สุด (ในแง่ของประสิทธิภาพ) เหตุใดจึงชั่ว
cbrandolino

5
@cbrandolino ไม่มีใครบอกว่ามันเป็นความชั่วร้าย ฉันแค่คิดว่ามันไม่เกี่ยวข้องกับคำถามทั้งหมด; เหมือน "นี่คือคำตอบสองข้อและนี่คือภาพลูกแมวบางตัวสำหรับผู้โหวตมากขึ้น"
salathe

5
if (substr($str, 0, strlen($prefix)) == $prefix) สามารถเปลี่ยนแปลงได้if (0 === strpos($str, $prefix))เพื่อหลีกเลี่ยงการจัดสรรหน่วยความจำที่ไม่จำเป็นในขณะที่ยังคงสามารถอ่านได้เหมือนเดิม :)
xDaizu

63

คุณสามารถใช้นิพจน์ทั่วไปที่มีสัญลักษณ์คาเร็ต ( ^) ซึ่งเชื่อมโยงการแข่งขันจนถึงจุดเริ่มต้นของสตริง:

$str = preg_replace('/^bla_/', '', $str);

ฉันสงสัยว่ามันใช้งานได้เร็วกว่าsubstr()เวอร์ชั่นหรือไม่ ... ฉันคิดว่ามันใช้ได้หรือไม่และควรทำเครื่องหมายเป็นคำตอบที่เหมาะสม
Flash Thunder

ยกเว้นจะต้องเป็นpreg_quote'd
vp_arth

ฉันคิดว่านี่เป็นสิ่งที่เจ็บปวดน้อยกว่ามากต่อสายตาของโปรแกรมเมอร์และใช้งานง่ายขึ้น แม้ว่ามันจะเสียประสิทธิภาพในการแก้ปัญหาที่แนะนำอื่น (ซึ่งฉันสงสัยจริงๆ) ฉันยังคงชอบสิ่งนี้
Fr0zenFyr

multibytenightmare เป็นอีกปัญหาหนึ่งของการแก้ปัญหาอื่น ๆ ในขณะที่มันใช้งานได้ดีถ้าการเข้ารหัสไฟล์นั้นถูกต้อง อย่างไรก็ตามมันไม่ควรอยู่ในขอบเขตของคำถามนี้ดังนั้นฉันจะไม่สนใจ
Fr0zenFyr

กลับมาพูดถึงว่าสิ่งนี้มีประโยชน์เพิ่มเติมในการทำงานกับอาร์เรย์ของหัวเรื่อง substrและstrposไม่สามารถยอมรับอาร์เรย์ได้ คุณจะไปได้ประสิทธิภาพที่แน่นอนเพิ่มขึ้นหากคุณจัดการกับอาเรย์ ไชโย!
Fr0zenFyr

20
function remove_prefix($text, $prefix) {
    if(0 === strpos($text, $prefix))
        $text = substr($text, strlen($prefix)).'';
    return $text;
}

10
.''ไม่จำเป็นต้อง
NateS

1
สำหรับสิ่งที่มีค่าเนื่องจากทุกคนดูเหมือนว่าจะเพิ่มประสิทธิภาพขนาดเล็กที่นี่อย่างนี้อย่างรวดเร็วโดยนับของฉัน มีการทำซ้ำ 1 ล้านครั้งในเวลา 0.17 วินาทีในขณะ(substr($str, 0, strlen($prefix)) == $prefix)ที่คำตอบที่ยอมรับนั้นเป็นเช่น. 37
billynoah

5

ที่นี่

$array = explode("_", $string);
if($array[0] == "bla") array_shift($array);
$string = implode("_", $array);

2
วัด 0.0000459153 วินาที :)
Fabio Mora

ความเร็วที่ดี _แต่นี่คือการกำหนดค่าตายตัวขึ้นอยู่กับเข็มที่ลงท้ายด้วย มีรุ่นทั่วไปหรือไม่
toddmo

0

ฉันคิดว่า substr_replace ทำในสิ่งที่คุณต้องการซึ่งคุณสามารถ จำกัด การแทนที่ให้เป็นส่วนหนึ่งของสตริงได้: http://nl3.php.net/manual/en/function.substr-replace.php (สิ่งนี้จะช่วยให้คุณมองเท่านั้น จุดเริ่มต้นของสตริง)

คุณสามารถใช้พารามิเตอร์ count ของ str_replace ( http://nl3.php.net/manual/en/function.str-replace.php ) สิ่งนี้จะช่วยให้คุณสามารถ จำกัด จำนวนของการเปลี่ยนโดยเริ่มจากด้านซ้าย แต่มัน จะไม่บังคับใช้ให้เป็นจุดเริ่มต้น


1
substr_replaceจะแทนที่อักขระในช่วงที่กำหนดโดยไม่คำนึงว่าเป็นส่วนนำหน้าที่คุณต้องการลบหรืออย่างอื่น OP ต้องการลบbla_“ เฉพาะเมื่อพบที่จุดเริ่มต้นของสตริง”
Olivier 'Ölbaum' Scherler

0

ความเร็วดี แต่นี่เป็นรหัสยากที่จะขึ้นอยู่กับเข็มที่ลงท้ายด้วย _ มีรุ่นทั่วไปหรือไม่ - toddmo 29 มิ.ย. เวลา 23:26 น

รุ่นทั่วไป:

$parts = explode($start, $full, 2);
if ($parts[0] === '') {
    $end = $parts[1];
} else {
    $fail = true;
}

มาตรฐานบางอย่าง:

<?php

$iters = 100000;
$start = "/aaaaaaa/bbbbbbbbbb";
$full = "/aaaaaaa/bbbbbbbbbb/cccccccccc/dddddddddd/eeeeeeeeee";
$end = '';

$fail = false;

$t0 = microtime(true);
for ($i = 0; $i < $iters; $i++) {
    if (strpos($full, $start) === 0) {
        $end = substr($full, strlen($start));
    } else {
        $fail = true;
    }
}
$t = microtime(true) - $t0;
printf("%16s : %f s\n", "strpos+strlen", $t);

$t0 = microtime(true);
for ($i = 0; $i < $iters; $i++) {
    $parts = explode($start, $full, 2);
    if ($parts[0] === '') {
        $end = $parts[1];
    } else {
        $fail = true;
    }
}
$t = microtime(true) - $t0;
printf("%16s : %f s\n", "explode", $t);

บนพีซีที่บ้านของฉันค่อนข้างเก่า:

$ php bench.php

ขาออก:

   strpos+strlen : 0.158388 s
         explode : 0.126772 s

0

นี่เป็นวิธีที่เร็วยิ่งขึ้น:

// strpos is faster than an unnecessary substr() and is built just for that 
if (strpos($str, $prefix) === 0) $str = substr($str, strlen($prefix));

0

การดำเนินการนี้จะลบการจับคู่ครั้งแรกที่ใดก็ตามที่พบเช่นเริ่มต้นหรือตรงกลางหรือสิ้นสุด

$str = substr($str, 0, strpos($str, $prefix)).substr($str, strpos($str, $prefix)+strlen($prefix));


-6

str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )

ตอนนี้ทำสิ่งที่คุณต้องการ

$str = "bla_string_bla_bla_bla";
str_replace("bla_","",$str,1);

7
str_replace()ฟังก์ชั่นของ$countพารามิเตอร์ที่คาดว่าจะเป็นตัวแปรส่งผ่านโดยการอ้างอิงเพื่อให้มีจำนวนของการเปลี่ยนที่พบไม่ จำกัด จำนวนทดแทน
อัล X

-6

ลบ www จากจุดเริ่มต้นของสตริงนี่เป็นวิธีที่ง่ายที่สุด (ltrim)

$a="www.google.com";
echo ltrim($a, "www.");

8
พารามิเตอร์ที่สองคือแผนที่ของตัวละครที่จะลบออกจากด้านซ้ายของสตริง ( php.net/manual/function.ltrim.php ) ดังนั้น: ltrim($a, "w.");จะทำงานเฉพาะเมื่อโดเมนจะไม่ขึ้นต้นด้วย "w" ผลในการltrim ('m.google.com', ".omg") le.com
fragmentedreality

แต่มันแก้ปัญหาเฉพาะของคำถาม +1
chulian

1
มันแก้ปัญหาเฉพาะที่เขาทำเพื่อคำตอบของเขา - ไม่ใช่ปัญหาของคำถาม แม้ว่าคุณจะไปด้วยltrimมันถูกใช้อย่างไม่ถูกต้อง พารามิเตอร์ที่สองคือรายการของตัวละครที่ควรจะถูกตัดแต่ง; ดังนั้นหนึ่ง"w."จะเพียงพอ
fragmentedreality

ฉันคิดว่า IMHO มันถูกต้องสำหรับคำถามและปัญหา
abkrim

2
หลังจากการทดสอบที่มีการทดสอบหลายครั้งเปลี่ยนความคิดเห็นของฉัน .... ไม่ทำงานสำหรับคำถามเกี่ยวกับสถานการณ์ใด ๆ
abkrim
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.