Xóa một chuỗi từ đầu chuỗi


146

Tôi có một chuỗi trông như thế này:

$str = "bla_string_bla_bla_bla";

Làm thế nào tôi có thể loại bỏ cái đầu tiên bla_; Nhưng chỉ khi nó được tìm thấy ở đầu chuỗi?

Với str_replace(), nó loại bỏ tất cả bla_ .


1
Bạn có thể thấy s($str)->replacePrefix('_bla')hữu ích, như được tìm thấy trong thư viện độc lập này .
caw

Câu trả lời:


339

Dạng đơn giản, không có regex:

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

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

Mất: 0,0369 ms (0,000,036,954 giây)

Và với:

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

Mất: 0,1749 ms (0,000,174,999 giây) lần chạy đầu tiên (biên dịch) và 0,0510 ms (0,000,051,021 giây) sau.

Hồ sơ trên máy chủ của tôi, rõ ràng.


8
Tôi chưa bao giờ thấy người điều hành ternary bị lạm dụng quá tệ, một điều đơn giản if(condition) { statement }sẽ rõ ràng hơn nhiều.
Tatu Ulmanen

4
@saledit: Tôi chấp nhận những lời chỉ trích. Đó là một sự tò mò cá nhân để xem cái gì là nhanh nhất.
Fabio Mora

51
@saledit, tôi không hiểu. Cả hai giải pháp dựa trên thành ngữ và regex đã được đề xuất: so sánh hai giải pháp về hiệu quả giúp tìm ra câu trả lời tốt nhất (một lần nữa về hiệu quả). Tại sao điều đó là xấu xa?
cbrandolino

5
@cbrandolino, không ai nói đó là xấu xa . Tôi chỉ nghĩ rằng nó hoàn toàn không liên quan đến câu hỏi; giống như "đây là hai giải pháp, và đây là hình ảnh của một số chú mèo con để có thêm sự ủng hộ".
saledit

5
if (substr($str, 0, strlen($prefix)) == $prefix) có thể được thay đổi if (0 === strpos($str, $prefix))để tránh phân bổ bộ nhớ không cần thiết trong khi vẫn giữ nguyên khả năng đọc như nhau :)
xDaizu

63

Bạn có thể sử dụng các biểu thức thông thường với ký hiệu dấu mũ ( ^) neo khớp với đầu chuỗi:

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

Tôi tự hỏi nếu nó hoạt động nhanh hơn substr()phiên bản ... Tôi đoán nó có, và nên được đánh dấu là câu trả lời thích hợp.
Flash Thunder

ngoại trừ nó phải là preg_quote'd
vp_arth

Tôi nghĩ rằng điều này ít đau đớn hơn nhiều đối với mắt của một lập trình viên và trực quan hơn. Ngay cả khi nó mất hiệu năng đối với một giải pháp được đề xuất khác (mà tôi thực sự nghi ngờ), tôi vẫn thích điều này.
Fr0zenFyr

multibyteác mộng là một vấn đề khác với các giải pháp khác trong khi điều này hoạt động tốt nếu mã hóa của tệp là chính xác. Dù sao, nó không nên nằm trong phạm vi của câu hỏi này nên tôi không quan tâm.
Fr0zenFyr

Trở lại để đề cập rằng điều này có một lợi ích bổ sung khi làm việc với một chuỗi các chuỗi chủ đề. substrstrposkhông thể chấp nhận một mảng. Ở đó bạn đi, tăng hiệu suất nhất định nếu bạn đang làm việc với một mảng. Chúc mừng!
Fr0zenFyr

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

10
Điều .''không cần thiết.
NateS

1
Đối với những gì nó có giá trị vì mọi người dường như tối ưu hóa vi mô ở đây, cái này luôn nhanh nhất theo tính của tôi. 1 triệu lần lặp lại đến vào lúc 17 giây, trong khi (substr($str, 0, strlen($prefix)) == $prefix)từ câu trả lời được chấp nhận giống như .37
billynoah

5

Đây.

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

2
Đo 0,0000459153 giây :)
Fabio Mora

Tốc độ đẹp, nhưng điều này được mã hóa cứng để phụ thuộc vào kim kết thúc bằng _. Có một phiên bản chung?
chập chững

0

Tôi nghĩ lớp nền có thể làm những gì bạn muốn, nơi bạn có thể giới hạn sự thay thế của mình trong một phần của chuỗi: http://nl3.php.net/manual/en/feft.substr-replace.php (Điều này sẽ cho phép bạn chỉ nhìn vào đầu chuỗi.)

Bạn có thể sử dụng tham số đếm của str numplace ( http://nl3.php.net/manual/en/feft.str-replace.php ), điều này sẽ cho phép bạn giới hạn số lần thay thế, bắt đầu từ bên trái, nhưng nó sẽ không thực thi nó ngay từ đầu.


1
substr_replacesẽ thay thế các ký tự trong phạm vi đã cho bất kể chúng là tiền tố bạn muốn xóa hay thứ gì khác. OP muốn xóa bla_chỉ khi nó được tìm thấy ở đầu chuỗi.
Olivier 'Ölbaum' Scherler

0

Tốc độ đẹp, nhưng điều này được mã hóa cứng để phụ thuộc vào kim kết thúc bằng _. Có một phiên bản chung? - chập chững ngày 29 tháng 6 lúc 23:26

Một phiên bản chung:

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

Một số điểm chuẩn:

<?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);

Trên PC khá cũ của tôi:

$ php bench.php

Đầu ra:

   strpos+strlen : 0.158388 s
         explode : 0.126772 s

0

Đây là một cách tiếp cận thậm chí nhanh hơn:

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

0

Điều này sẽ loại bỏ trận đấu đầu tiên bất cứ nơi nào nó được tìm thấy, tức là bắt đầu hoặc giữa hoặc kết thúc.

$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 ] )

bây giờ làm những gì bạn muốn

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

7
Các str_replace()nhân chức năng $counttham số được kỳ vọng sẽ là một biến thông qua tham khảo để chứa các số thay thế được tìm thấy, không hạn chế số lượng thay thế.
AL the X

-6

Xóa www. từ đầu chuỗi, đây là cách dễ nhất (ltrim)

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

8
Tham số thứ hai là một bản đồ các ký tự được xóa khỏi phía bên trái của chuỗi ( php.net/manual/feft.ltrim.php ). Do đó: ltrim($a, "w.");sẽ chỉ thực hiện công việc nếu tên miền không bắt đầu bằng "w". ltrim ('m.google.com', ".omg")kết quả trong le.com.
phân mảnh thực tế

nhưng nó giải quyết được vấn đề cụ thể của câu hỏi, +1
chulian

1
nó thực sự giải quyết được vấn đề cụ thể mà anh ấy đã đưa ra cho câu trả lời của mình - không phải vấn đề của câu hỏi. ngay cả khi bạn sẽ đi với ltrim, nó được sử dụng không chính xác. tham số thứ hai là một danh sách các ký tự nên được cắt bớt; do đó một cái "w."sẽ là đủ.
phân mảnh thực tế

Tôi nghĩ, IMHO, nó đúng cho câu hỏi và cho vấn đề.
abkrim

2
Sau khi thử nghiệm với một số thử nghiệm thay đổi quan điểm của tôi .... không hoạt động cho câu hỏi về bất kỳ tình huống nào
abkrim
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.