PHP Preg-Replace More Than One Underscore

PHP Preg-Replace more than one underscore

preg_replace('/[_]+/', '_', $your_string);

Replacing all proceeding underscores with 1 underscore using a regex?

preg_replace('/_+/', '_', $string);

thought for something so simple, you'd get better performance from str_replace().

preg_replace all numbers before underscore, than replace underscore and end

You can use preg_replace to remove these prefixes using regexes.

echo preg_replace('/^\d+_/', '', '0_xxxx');
// Will output 'xxxx'

This example code will remove all numbers followed by an underscore from the start of your string.

preg_replace not replacing underscore

The character class range is for a range of characters between two code points. The character _ is included in the range A-z, and you can see this by looking at the ASCII table:


... Y Z [ \ ] ^ _ ` a b ...

So it's not only the underscore that's being let through, but those other characters you see above, as stated in the documentation:

Ranges operate in ASCII collating sequence. ... For example, [W-c] is equivalent to [][\^_`wxyzabc].

To prevent this from happening, you can perform a case insensitive match with a single character range in your character class:

$name = preg_replace('/[^a-z0-9 ]/i', '', $str);

PHP preg_replace occurrence of any text after the very last underscore

Depending on your common search string and your version of PCRE, either preg_replace or strrpos will probably fare best:

Functions

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

Test harness

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;
}

Results

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

Note that (at least on my set-up with PHP 5.4.0), preg_replace gives strrpos a run for its money until there are a large number of underscores preceding the last one.

EDIT: I plugged bfrohs's regex into the suite and unless the underscore to replace is near the beginning of the string, it doesn't do very well:

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

preg_replace that only removes more than 2 lines

You can use:

echo preg_replace('/(\R)(\R){2,}/', "$1$2", $str);

Demo & explanation

Replacing everything other than alphanumeric, hyphen, period and underscore in a string

- inside character class denotes range, e.g. 0-9. So, you should keep it in first, last or escape it if you want to put it in middle.

Also \w => [A-Za-z0-9_]

Finally, you can use this regex

[^\w.-]

Regex Demo

PHP Code

$re = "/[^\\w.-]/"; 
$str = "A\'skljdsg\\\sk//dgj@@@////#``flkl_dfd-_-sfsfs-fk kgj.docx";

$result = preg_replace($re, "", $str);

Ideone Demo

If you want to include space also, use

[^\w. -]


Related Topics



Leave a reply



Submit