I have a string that looks like this:
$str = "bla_string_bla_bla_bla";
How can I remove the first bla_
; but only if it's found at the beginning of the string?
With str_replace()
, it removes all bla_
's.
I have a string that looks like this:
$str = "bla_string_bla_bla_bla";
How can I remove the first bla_
; but only if it's found at the beginning of the string?
With str_replace()
, it removes all bla_
's.
Plain form, without regex:
$prefix = 'bla_';
$str = 'bla_string_bla_bla_bla';
if (substr($str, 0, strlen($prefix)) == $prefix) {
$str = substr($str, strlen($prefix));
}
Takes: 0.0369 ms (0.000,036,954 seconds)
And with:
$prefix = 'bla_';
$str = 'bla_string_bla_bla_bla';
$str = preg_replace('/^' . preg_quote($prefix, '/') . '/', '', $str);
Takes: 0.1749 ms (0.000,174,999 seconds) the 1st run (compiling), and 0.0510 ms (0.000,051,021 seconds) after.
Profiled on my server, obviously.
if(condition) { statement }
would have been so much clearer. –
Monogamist preg_replace('/^' . preg_quote($prefix,'/') . '/', '', $str);
–
Vardar $str = substr($str, strlen($prefix));
rather than $str = substr($str, strlen($prefix), strlen($str));
? –
Luik length
) can be omitted, but furthermore strlen($str)
is always going to exceed the resulting length - strlen(prefix)
character count. The 2-argument substr
should be used here. –
Nosedive if (substr($str, 0, strlen($prefix)) == $prefix)
can be changed for if (0 === strpos($str, $prefix))
to avoid unnecessary memory allocation while keeping the same readability :) –
Audie ===
) because substr
may return false –
Sentimentalize ltrim($str, $prefix)
? –
Jenniejennifer ltrim
has a different purpose, it matches against chars, not strings. E.g. php -r "print ltrim('foo_bar', 'of_');"
heads to bar
anyway. –
Hubbell str_starts_with()
instead of the substr..
construct...: php.net/manual/de/function.str-starts-with.php –
Gamages You can use regular expressions with the caret symbol (^
) which anchors the match to the beginning of the string:
$str = preg_replace('/^bla_/', '', $str);
substr()
version... I guess it does, and should be marked as proper answer. –
Kepner preg_quote
'd –
Offspring multibyte
nightmare is another issue with other solutions while this works well if the encoding of the file is correct. Anyway, it shouldn't be in the scope of this question so I wouldn't care. –
Roundabout substr
and strpos
can't accept an array. There you go, a definite performance gain if you are dealing with an array. Cheers! –
Roundabout function remove_prefix($text, $prefix) {
if(0 === strpos($text, $prefix))
$text = substr($text, strlen($prefix)).'';
return $text;
}
.''
isn't needed. –
Hoopes (substr($str, 0, strlen($prefix)) == $prefix)
from the accepted answer was more like .37 –
Scarfskin In PHP 8+ we can simplify using the str_starts_with()
function:
$str = "bla_string_bla_bla_bla";
$prefix = "bla_";
if (str_starts_with($str, $prefix)) {
$str = substr($str, strlen($prefix));
}
https://www.php.net/manual/en/function.str-starts-with.php
EDIT: Fixed a typo (closing bracket) in the example code.
Here's an even faster approach:
// strpos is faster than an unnecessary substr() and is built just for that
if (strpos($str, $prefix) === 0) $str = substr($str, strlen($prefix));
Here.
$array = explode("_", $string);
if($array[0] == "bla") array_shift($array);
$string = implode("_", $array);
_
. Is there a general version? –
Hickory explode()
, but if you have to, then you should use its limit parameter. This answer is missing its educational explanation. –
Cowpoke Nice speed, but this is hard-coded to depend on the needle ending with _. Is there a general version? – toddmo Jun 29 at 23:26
A general version:
$parts = explode($start, $full, 2);
if ($parts[0] === '') {
$end = $parts[1];
} else {
$fail = true;
}
Some benchmarks:
<?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);
On my quite old home PC:
$ php bench.php
Outputs:
strpos+strlen : 0.158388 s
explode : 0.126772 s
Lots of different answers here. All seemingly based on string analysis. Here is my take on this using PHP explode
to break up the string into an array of exactly two values and cleanly returning only the second value:
$str = "bla_string_bla_bla_bla";
$str_parts = explode('bla_', $str, 2);
$str_parts = array_filter($str_parts);
$final = array_shift($str_parts);
echo $final;
Output will be:
string_bla_bla_bla
Symfony users can install the string component and use trimPrefix()
u('file-image-0001.png')->trimPrefix('file-'); // 'image-0001.png'
I generally don't have an appetite for techniques that need 3 function calls or generate and array to produce a string when a single regex function will do.
I want to mention that if you use pattern delimiters that are covered in the default mask of preg_quote()
, then you won't need to nominate the second parameter (#
is one of those characters).
Documenation: https://www.php.net/manual/en/function.preg-quote.php
The special regular expression characters are: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : - #
Note that / is not a special regular expression character.
Code: (Demo)
$str = preg_replace('#^' . preg_quote($prefix) . '#'), '', $str);
For completeness, I want to add to this page that sscanf()
can be a suitable technique so long as you are in "control" of the prefix string and can confidently assign all characters after the prefix to a placeholder. In the asker's sample input, there are no spaces in the input string, so %s
will suffice. If there are any spaces in the substring after the prefix, then %s
is no good -- you might use a negated expression with a character that will not occur like %[^~]
or similar. This technique will modify the input string by reference if needed. (Demo)
sscanf($str, "$prefix%s", $str);
I'll admit that sscanf()
isn't the most intuitive tool for this task and there are scenarios where it is unsuitable, but for the presented task the single function call works as desired. For cases when you have a prefix followed by a number, sscanf()
with %d
in the format parameter will auto-cast the matched string as an integer. So there may be some scenarios where it is more ideal than a preg_
function call.
I think substr_replace does what you want, where you can limit your replace to part of your string: https://www.php.net/manual/en/function.substr-replace.php (This will enable you to only look at the beginning of the string.)
You could use the count parameter of str_replace ( https://www.php.net/manual/en/function.str-replace.php ), this will allow you to limit the number of replacements, starting from the left, but it will not enforce it to be at the beginning.
substr_replace
will replace the characters in the given range regardless of whether they’re the prefix you want to remove or something else. The OP wants to remove bla_
“only if it's found at the beginning of the string.” –
Killigrew str_replace()
's count parameter DOES NOT allow you to limit the number of replacements. –
Cowpoke © 2022 - 2024 — McMap. All rights reserved.
s($str)->replacePrefix('_bla')
helpful, as found in this standalone library. – Meanly