PHP แทนที่เกิดขึ้นครั้งสุดท้ายของสตริงในสตริงหรือไม่


145

ใครรู้วิธีที่รวดเร็วมากในการแทนที่การเกิดขึ้นครั้งสุดท้ายของสตริงด้วยสายอักขระอื่นในสตริง?


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

คำตอบ:


228

คุณสามารถใช้ฟังก์ชั่นนี้:

function str_lreplace($search, $replace, $subject)
{
    $pos = strrpos($subject, $search);

    if($pos !== false)
    {
        $subject = substr_replace($subject, $replace, $pos, strlen($search));
    }

    return $subject;
}

สิ่งนี้ยังคงกลับมาจริงไม่ว่าจะเกิดอะไรขึ้น พิจารณาแก้ไขเป็น: ถ้า ($ pos) {$ subject = substr_replace ($ subject, $ replace, $ pos, strlen ($ search)); ส่งคืน $ subject; } else {return false; }
Jazzy

4
@ Jason มันไม่ได้กลับมาTRUEไม่ว่าอะไรจะเกิดขึ้น มันส่งคืนสตริงไม่ว่าจะเกิดอะไรขึ้น หากการแทนที่ไม่สามารถทำได้จะส่งคืนต้นฉบับ$subjectเหมือนsubstr_replace และstr_replaceทำได้
Mischa

@Mischa ไม่เหมือนกันในกรณีนี้เหรอ? ฉันพยายามทำบางสิ่งเช่น! str_lreplace แต่ถ้ามันไม่ส่งคืนเท็จมันก็ถือว่าเป็นจริงใช่ไหม ไม่ว่าจะด้วยวิธีใดสิ่งนี้ช่วยฉันและฉันก็ยินดี ขอบคุณ
Jazzy

1
ใช้งานได้อย่างไร? strpos — Find the position of the first occurrence of a substring in a string- แก้ไข: ว้าว Php อัจฉริยะทำหน้าที่เรียกว่าstrposและstrrpos? ขอบคุณ ....
BarryBones41

1
@Barry เป็นกรณีหนึ่งที่ PHP ไม่สมควรได้รับโทษ :-) ชื่อจะมีลวดลายในทศวรรษที่ผ่านมานี้เก่าstrstr, strrstrของห้องสมุด C มาตรฐานซึ่งมีฟังก์ชั่นเดียวกัน (แต่พวกเขาต้องเปลี่ยนชื่อเหรอ?)
alexis

30

อีก 1 ซับ แต่ไม่มี preg:

$subject = 'bourbon, scotch, beer';
$search = ',';
$replace = ', and';

echo strrev(implode(strrev($replace), explode(strrev($search), strrev($subject), 2))); //output: bourbon, scotch, and beer

3
FWIW โซลูชันที่ยอมรับนั้นเร็วกว่าโซลูชันนี้ประมาณ 35%
JustCarty

27
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace(strrev("/$find/"),strrev($replace),strrev($string),1);
echo strrev($result); //output: this is my world, not my farm

ทางออกที่ยอดเยี่ยมในความคิดของฉันและยังคงเข้าใจได้ง่าย
Blackbam

เหตุใดจึงทำงานกับสตริงทั้งหมดกลับด้าน มีประสิทธิภาพบางอย่าง (ฉันสมมติว่า) เพิ่มขึ้นเมื่อใช้นิพจน์ทั่วไปหรือไม่
Kamafeather

ไม่จริงลดประสิทธิภาพ แต่เป็นเพราะคุณต้องการเหตุการณ์ล่าสุดเท่านั้นดังนั้นคุณจึง จำกัด การค้นหาไว้ที่หนึ่งและย้อนกลับทุกอย่างหากคุณต้องการสิ่งแรกคุณไม่จำเป็นต้องย้อนกลับเลย
Tofandel

15

โซลูชันที่มีขนาดกะทัดรัดต่อไปนี้ใช้การยืนยันแบบ lookahead ที่เป็นบวกของ PCREเพื่อให้ตรงกับการเกิด substring ที่น่าสนใจล่าสุดนั่นคือการเกิด substring ที่ไม่เกิดขึ้นตามมาด้วยเหตุการณ์อื่น ๆ ของ substring เดียวกัน ดังนั้นตัวอย่างเช่นแทนที่ด้วยlast 'fox''dog'

$string = 'The quick brown fox, fox, fox jumps over the lazy fox!!!';
echo preg_replace('/(fox(?!.*fox))/', 'dog', $string);

เอาท์พุท: 

The quick brown fox, fox, fox jumps over the lazy dog!!!

5
ความคิดนั้นดี แต่รหัสไม่ได้ ต้องเป็น:$string = 'The quick brown fox, fox, fox jumps over the lazy fox!!!'; echo preg_replace('/(fox(?!.*fox))/', 'dog', $string);
Roemer

อันที่จริงรหัสที่ฉันโพสต์นั้นได้เปลี่ยนอินสแตนซ์ทั้งหมดของ "จิ้งจอก" ยกเว้นอันสุดท้ายเป็น "สุนัข" แต่สิ่งที่เราต้องการนั้นตรงกันข้าม ขอบคุณสำหรับการชี้ให้เห็นว่าการแทนที่? = ด้วย?! แก้ไขปัญหา
John Sonderson

11

คุณสามารถทำได้:

$str = 'Hello world';
$str = rtrim($str, 'world') . 'John';

ผลลัพธ์คือ 'Hello John';

ความนับถือ


4
ใช้งานได้ตราบใดที่ไม่มีอักขระซ้ำ ในสถานการณ์ของฉันฉันกำลังตัดหมายเลขหน้าออกจากวันที่เก็บถาวรดังนั้นฉันจึงมี "2015-12 / 2" และใช้เวลาทั้งหมด / และทั้งหมด 2 แห่งในตอนท้ายกลายเป็น "2015-1"
Mike

วิธีนี้จะใช้งานได้หากการค้นหาที่เกิดขึ้นครั้งสุดท้ายเป็นคำสุดท้ายและไม่มีตัวอักษรเพิ่มเติมหลังจากนั้น
AwesomeGuy

สิ่งนี้ไม่ทำงานเพราะrtrimไม่ได้ทำงานอย่างที่คุณคิด มันจะตัดจากจุดสิ้นสุดอักขระใด ๆ ที่มีอยู่ในสตริงการค้นหาตามลำดับใด ๆ (และเพิ่มการแทนที่เสมอ) เช่น "Hello word" -> "Hello John", "Hello lord" -> "Hello John", "Hello John", "Hello มอเตอร์ "->" Hello motJohn "," Hello worldy "->" Hello worldyJohn "
Jake

5

สิ่งนี้จะได้ผล:

function str_lreplace($search, $replace, $subject)
{
    return preg_replace('~(.*)' . preg_quote($search, '~') . '(.*?)~', '$1' . $replace . '$2', $subject, 1);
}

อัปเดตเวอร์ชันย่อที่กระชับยิ่งขึ้นเล็กน้อย ( http://ideone.com/B8i4o ):

function str_lreplace($search, $replace, $subject)
{
    return preg_replace('~(.*)' . preg_quote($search, '~') . '~', '$1' . $replace, $subject, 1);
}

ฉันทำผิดหรือเปล่า? ถ้าเป็นเช่นนั้นเพียงแค่ไม่สนใจฉัน :) ||| echo str_lreplace ("x", "y", "this x หรือ x นั้น"); => เอาต์พุต: "y" ดู: ideone.com/UXuTo
edorian

@edorian: อ๊ะ! ขออภัยที่ผมโพสต์รีบร้อนรุ่นที่ถูกต้องอยู่ที่นี่: ideone.com/vR073
Alix Axel

5

เพียงหนึ่งบรรทัดของรหัส (ตอบช้า แต่มันก็คุ้มที่จะเพิ่ม):

$string = 'The quick brown fox jumps over the lazy dog';
$find_me = 'dog';

preg_replace('/'. $find_me .'$/', '', $string);

สิ้นสุด $ ระบุจุดสิ้นสุดของสตริง


5

นี่เป็นคำถามโบราณ แต่ทำไมทุกคนถึงมองเห็นโซลูชันที่ใช้ regexp ที่ง่ายที่สุด ปริมาณ regexp ปกติเป็นคนโลภ! หากคุณต้องการค้นหาอินสแตนซ์สุดท้ายของรูปแบบเพียงติด.*ไว้ด้านหน้า นี่คือวิธี:

$text = "The quick brown fox, fox, fox, fox, jumps over etc.";
$fixed = preg_replace("((.*)fox)", "$1DUCK", $text);
print($fixed);

สิ่งนี้จะแทนที่อินสแตนซ์สุดท้ายของ "จิ้งจอก" เป็น "DUCK" อย่างที่ควรจะเป็นและพิมพ์:

The quick brown fox, fox, fox, DUCK, jumps over etc.

1
ขอบคุณ! ฟังก์ชั่นที่สมบูรณ์แบบในการพันรอบการแสดงออกของฉันเพื่อให้บรรลุ ในกรณีของฉันฉันกำลังแทนที่เครื่องหมายจุลภาคสุดท้ายด้วย "และ" ดีใจที่ฉันเลื่อนลงเล็กน้อยในรายการคำตอบนี้
rlhane

3
$string = "picture_0007_value";
$findChar =strrpos($string,"_");
if($findChar !== FALSE) {
  $string[$findChar]=".";
}

echo $string;

นอกเหนือจากความผิดพลาดในรหัส Faruk Unal มีสิ่งที่ดีที่สุด ฟังก์ชั่นหนึ่งจะหลอกลวง


คุณต้องตรวจสอบว่า$ findCharไม่ใช่เท็จ (เช่นเดียวกับคำตอบที่ยอมรับ) หากสตริงไม่มีสตริงการค้นหาคุณจะได้รับการแจ้งให้ทราบและจะมีการแทนที่อักขระตัวแรก
ปุย

สิ่งนี้ยอดเยี่ยม แต่เนื่องจากมันสามารถแทนที่ได้เพียง 1 ตัวอักษรด้วย 1 ตัวเท่านั้น
Pete

3

คุณสามารถใช้ strrpos () เพื่อค้นหาการแข่งขันครั้งสุดท้าย

$string = "picture_0007_value";
$findChar =strrpos($string,"_");

$string[$findChar]=".";

echo $string;

เอาต์พุต: picture_0007.value


2

จดชวเลขสำหรับคำตอบที่ยอมรับ

function str_lreplace($search, $replace, $subject){ 
    return is_numeric($pos=strrpos($subject,$search))?
    substr_replace($subject,$replace,$pos,strlen($search)):$subject;
}


0

ใช้ "$" ในการแสดงออก reg เพื่อให้ตรงกับจุดสิ้นสุดของสตริง

$string = 'The quick brown fox jumps over the lazy fox';
echo preg_replace('/fox$/', 'dog', $string);

//output
'The quick brown fox jumps over the lazy dog'

4
สิ่งนี้ใช้งานได้หากการเกิดขึ้นครั้งสุดท้ายอยู่ในตอนท้ายของสตริงideone.com/nbNSNq
cawecoy

1
สิ่งนี้จะไม่ทำงานหากมีตัวละครอื่นปรากฏขึ้นหลังจาก 'จิ้งจอก' ตัวสุดท้าย
John Sonderson

0

สำหรับผู้ที่สนใจ: ฉันได้เขียนฟังก์ชั่นที่ใช้ preg_match เพื่อให้คุณสามารถแทนที่จากด้านขวาโดยใช้ regex

function preg_rreplace($search, $replace, $subject) {
    preg_match_all($search, $subject, $matches, PREG_SET_ORDER);
    $lastMatch = end($matches);

    if ($lastMatch && false !== $pos = strrpos($subject, $lastMatchedStr = $lastMatch[0])) {
        $subject = substr_replace($subject, $replace, $pos, strlen($lastMatchedStr));
    }

    return $subject;
}

หรือเป็นการผสมผสาน / การใช้งานของทั้งสองตัวเลือก:

function str_rreplace($search, $replace, $subject) {
    return (false !== $pos = strrpos($subject, $search)) ?
        substr_replace($subject, $replace, $pos, strlen($search)) : $subject;
}
function preg_rreplace($search, $replace, $subject) {
    preg_match_all($search, $subject, $matches, PREG_SET_ORDER);
    return ($lastMatch = end($matches)) ? str_rreplace($lastMatch[0], $replace, $subject) : $subject;
}

อ้างอิงจากhttps://stackoverflow.com/a/3835653/3017716และhttps://stackoverflow.com/a/23343396/3017716

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