24

How can I replace a set of words that look like:

SomeText

to

Some_Text

?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Alex
  • 66,732
  • 177
  • 439
  • 641
  • *(related)* [exploding-uppercasedcamelcase-to-upper-cased-camel-case-in-php](http://stackoverflow.com/questions/3275837/exploding-uppercasedcamelcase-to-upper-cased-camel-case-in-php) – edorian Jun 03 '11 at 12:42

5 Answers5

40

This can easily be achieved using a regular expression:

$result = preg_replace('/\B([A-Z])/', '_$1', $subject);

a brief explanation of the regex:

  • \B asserts position at a word boundary.
  • [A-Z] matches any uppercase characters from A-Z.
  • () wraps the match in a back reference number 1.

Then we replace with '_$1' which means replace the match with an [underscore + backreference 1]

josef.van.niekerk
  • 11,941
  • 20
  • 97
  • 157
  • You probably would only be able to tell which one is faster by means of benchmarking your solution. The difference would probably be minute. The operations get slower as the regex grows more complicated. – josef.van.niekerk Jun 03 '11 at 12:35
  • This one avoids lookahead and look-behind assertions, which in my opinion makes it faster. Also it is more readable. Just means insert underscore before capital letter that comes after non-word-boundary. – Billy Moon Jun 03 '11 at 12:36
  • But it gives `Some_Text and Some_Other_Text and s_O_M_Em_O_R_Et_E_X_T` for `SomeText and SomeOtherText and sOMEmOREtEXT`. Are you OK with it? – Amil Waduwawara Jun 03 '11 at 12:44
  • 1
    Ok, nice try - what if the string is "ILovePHPAndXMLSoMuсh" and the result is: I_Love_P_H_P_And_X_M_L_So_Much, but I need PHP and XML? – Arthur Kushman Apr 18 '15 at 16:26
10
$s1 = "ThisIsATest";
$s2 = preg_replace("/(?<=[a-zA-Z])(?=[A-Z])/", "_", $s1);

echo $s2;  //  "This_Is_A_Test"

Explanation:

The regex uses two look-around assertions (one look-behind and one look-ahead) to find spots in the string where an underscore should be inserted.

(?<=[a-zA-Z])   # a position that is preceded by an ASCII letter
(?=[A-Z])       # a position that is followed by an uppercase ASCII letter

The first assertion makes sure that no underscore is inserted at the start of the string.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
4

$result = strtolower(preg_replace('/(.)([A-Z])/', '$1_$2', $subject));

Converts:

HelloKittyOlolo
Declaration
CrabCoreForefer
TestTest
testTest

To:

hello_kitty_ololo
declaration
crab_core_forefer
test_test
test_test
Aldekein
  • 3,538
  • 2
  • 29
  • 33
4

The simplest way to do this is with a regular expression replacement.

For example:

substr(preg_replace('/([A-Z])/', '_$1', 'SomeText'),1);

The substr call there is to remove a leading '_'

Simon Elliston Ball
  • 4,375
  • 1
  • 21
  • 18
3
<?php 

$string = "SomeTestString";
$list = split(",",substr(preg_replace("/([A-Z])/",',\\1',$string),1));
$text = "";

foreach ($list as $value) {
    $text .= $value."_";
}

echo substr($text,0,-1); // remove the extra "_" at the end of the string

?>