PHP preg_replace the appearance of any text after the most recent underscore

I can do it with explode(or have some fun with strrpos), but I prefer to use it preg_replace, because it should be a little faster, I think (right?). In addition, it is concise and elegant.

The goal is to get a type string a_b_cto get another sting , where are the characters following the last_ , where the passed string is replaced.

I am not good at regular expression. I have to take the time to buy a good book in my office. In any case, I tried this regex '/_(.*)$/'as matching the end of the line, capturing any character following the last underscore.

What is wrong with my argument?

// Do it using explode
function foo($string, $replacement)
{
    $pieces = explode('_', $string);
    array_pop($pieces);
    return implode('_', array_merge($pieces, array($replacement)));
}

// Do it using regular expression (not working)
function bar($string, $replacement)
{
    return preg_replace('/_(.*)$/', $replacement, $string);
}

echo foo('a_b_c', 3); // Prints a_b_3
echo bar('a_b_c', 3); // Prints a3 wrong!!!
+3
7

PCRE , preg_replace strrpos:

function usingExplode($string, $replacement) {
    $pieces = explode('_', $string);
    array_pop($pieces);
    return implode('_', array_merge($pieces, array($replacement)));
}

function usingStrrpos($string, $replacement) {
    return substr($string, 0, strrpos($string, '_') + 1) . $replacement;
}

function usingPreg($string, $replacement) {
    return preg_replace('/_[^_]*$/', '_' . $replacement, $string);
}

function speedTest($function, $string, $count = 100000) {
    $start = microtime(true);

    for ($i = 0; $i < $count; $i++) {
        $function($string, 'replacement');
    }

    $end = microtime(true);

    printf('%-12s: %01.2fs%s', $function, $end - $start, PHP_EOL);
}

$tests = array('a_b_c', 'abcdefghijklmnopqrstuvwxy_z', 'a_bcdefghijklmnopqrstuvwxyz', 'a_b_c_d_e_f_g_h_i_j_k_l_m_n_o_p_q_r_s_t_u_v_w_x_y_z');

foreach ($tests as $test) {
    echo $test . ':' . PHP_EOL;
    speedTest('usingExplode', $test);
    speedTest('usingStrrpos', $test);
    speedTest('usingPreg',    $test);
    echo PHP_EOL;
}

a_b_c:
usingExplode: 0.64s
usingStrrpos: 0.34s
usingPreg   : 0.33s

abcdefghijklmnopqrstuvwxy_z:
usingExplode: 0.61s
usingStrrpos: 0.32s
usingPreg   : 0.32s

a_bcdefghijklmnopqrstuvwxyz:
usingExplode: 0.60s
usingStrrpos: 0.32s
usingPreg   : 0.32s

a_b_c_d_e_f_g_h_i_j_k_l_m_n_o_p_q_r_s_t_u_v_w_x_y_z:
usingExplode: 1.39s
usingStrrpos: 0.32s
usingPreg   : 0.71s

, ( , PHP 5.4.0) preg_replace strrpos , , .

EDIT: bfrohs regex , , t :

a_b_c:
usingPreg2: 0.40s

abcdefghijklmnopqrstuvwxy_z:
usingPreg2: 1.91s

a_bcdefghijklmnopqrstuvwxyz:
usingPreg2: 0.38s

a_b_c_d_e_f_g_h_i_j_k_l_m_n_o_p_q_r_s_t_u_v_w_x_y_z:
usingPreg2: 1.04s
+2

, , , :

([^_]*)$

, , . , $1 .

+3

, . - :

'/_([^_]*)$/'
+1

expresson /_(.*)$/ , , . " " , , . , 'a_b_c' 'a'.

, . ( ) [^_], , .

, , . , .

function bar($string, $replacement)
{
    return preg_replace('/[^_]*$/', $replacement, $string, 1);
}
+1

strpos , preg_replace, . ( ) , .

: http://lzone.de/articles/php-string-search.htm

+1

'/([^_]+)$/' , , .

. . , .

0

It looks like a smiley, but I think it should work:

return preg_replace('/(.*_).*/', $replacement, $string);
0
source

All Articles