¿Cómo convertir "camelCase" a "Camel Case"?

174

He estado tratando de conseguir una orden de expresiones regulares JavaScript para convertir algo así como "thisString"en "This String"pero lo más cerca que he recibido está reemplazando una carta, lo que resulta en algo así como "Thi String"o "This tring". ¿Algunas ideas?

Para aclarar que puedo manejar la simplicidad de la capitalización de una carta, simplemente no lo soy fuerte con expresiones regulares, y la división "somethingLikeThis"en "something Like This"es donde estoy teniendo problemas.

Un mago lo hizo
fuente
66
¿Cómo es esto un duplicado de eso? Todo lo que hace es poner en mayúscula el primer carácter de una cadena, nada parecido a lo que quiero hacer.
Un mago lo hizo
Hmm no es un engaño de la pregunta, pero el resultado podría ser el mismo. ¿O no es eso lo que querías hacer? ¿Elaborar más?
Superfro
Para la práctica de expresiones regulares, sugiero que RegExr o Expresso se prueben y solo miren todas las preguntas de expresiones regulares en SO e intenten responderlas. Las expresiones regulares no son la cosa más simple del mundo, pero recuerda que si tu expresión regular te confunde, entonces divídela y trabaja en pedazos.
josh.trow

Respuestas:

399
"thisStringIsGood"
    // insert a space before all caps
    .replace(/([A-Z])/g, ' $1')
    // uppercase the first character
    .replace(/^./, function(str){ return str.toUpperCase(); })

muestra

This String Is Good

Vincent Robert
fuente
1
Buen hombre, dividiéndolo. Solo recuerde el consejo de Bobince: stackoverflow.com/questions/1732348/…
josh.trow
¿Estás seguro de que esto es compatible con IE? Acabo de probar en IETester7 y recibí un error.
strongriley
3
También agrega: si tiene un acrónimo de mayúsculas que desea mantener juntos, puede cambiar la primera expresión regular a "/ ([AZ] [az]) /"
jackfrster
2
"This" -> "This" (espacio de prefijo no deseado). Tal vez cámbielo a: str.slice (0, 1) .toUpperCase () + str.slice (1) .replace (/ ([AZ]) / g, '$ 1')
Mark Vayngrib
1
@ColdCerberus Puede usar: str.replace(/((?<!^)[A-Z](?![A-Z]))(?=\S)/g, ' $1').replace(/^./, s => s.toUpperCase() );Se convertirá userIDa User ID, e incluso se convertirá userIDFieldaUser ID Field
Eugene Mala
87

Tenía un interés inactivo en esto, particularmente en el manejo de secuencias de mayúsculas, como en xmlHTTPRequest. Las funciones enumeradas producirían "Solicitud HTTP Xml" o "Solicitud HTTP Xml", la mía produce "Solicitud HTTP Xml".

function unCamelCase (str){
    return str
        // insert a space between lower & upper
        .replace(/([a-z])([A-Z])/g, '$1 $2')
        // space before last upper in a sequence followed by lower
        .replace(/\b([A-Z]+)([A-Z])([a-z])/, '$1 $2$3')
        // uppercase the first character
        .replace(/^./, function(str){ return str.toUpperCase(); })
}

También hay una versión de String.prototype en una esencia .

Matt Wiebe
fuente
Lo mismo se puede lograr con 2 llamadas de reemplazo:str.replace(/((?<!^)[A-Z](?![A-Z]))(?=\S)/g, ' $1').replace(/^./, s => s.toUpperCase() )
Eugene Mala
22

Esto se puede hacer de manera concisa con regex lookahead ( demostración en vivo ):

function splitCamelCaseToString(s) {
    return s.split(/(?=[A-Z])/).join(' ');
}

(Pensé que la gbandera (global) era necesaria, pero curiosamente, no lo es en este caso particular).

Usar lookahead con splitasegura que la letra mayúscula coincidente no se consuma y evita tratar con un espacio inicial si UpperCamelCase es algo con lo que debe lidiar. Para poner en mayúscula la primera letra de cada uno, puede usar:

function splitCamelCaseToString(s) {
    return s.split(/(?=[A-Z])/).map(function(p) {
        return p.charAt(0).toUpperCase() + p.slice(1);
    }).join(' ');
}

El mapmétodo de matriz es una característica de ES5, pero aún puede usarlo en navegadores antiguos con algún código de MDC . Alternativamente, puede iterar sobre los elementos de la matriz utilizando un forbucle.

Por favor levantese
fuente
La primera función la divide, pero no PascalCase la primera palabra. La segunda función falla en un caso sin camelCased. (p. ej .: 'id')
Demencial
16

Creo que esto debería ser capaz de manejar caracteres en mayúsculas consecutivos, así como camelCase simple.

Por ejemplo: someVariable => someVariable, pero ABCCode! = Código ABC.

La expresión regular a continuación funciona en su ejemplo, pero también en el ejemplo común de representar abreviaturas en camcelCase.

"somethingLikeThis"
    .replace(/([a-z])([A-Z])/g, '$1 $2')
    .replace(/([A-Z])([a-z])/g, ' $1$2')
    .replace(/\ +/g, ' ') => "something Like This"

"someVariableWithABCCode"
    .replace(/([a-z])([A-Z])/g, '$1 $2')
    .replace(/([A-Z])([a-z])/g, ' $1$2')
    .replace(/\ +/g, ' ') => "some Variable With ABC Code"

También puede ajustar como se indica arriba para capitalizar el primer carácter.

thegreenpizza
fuente
10
function spacecamel(s){
    return s.replace(/([a-z])([A-Z])/g, '$1 $2');
}

spacecamel ('algo como esto')

// valor devuelto: algo como esto

Kennebec
fuente
1
¡Buena esa! esto es exactamente lo que necesitaba que quería dividir, por ejemplo: DiscoveryChannel y HBO, otras respuestas me dieron Discovery Channel y HBO, pero su respuesta me funcionó, ya que HBO se mantuvo intacto, ¡gracias!
AJS
8

Lodash maneja esto muy bien con_.startCase()

Lawrence Chang
fuente
4

Una solución que también maneja números:

function capSplit(str){
   return str.replace
      ( /(^[a-z]+)|[0-9]+|[A-Z][a-z]+|[A-Z]+(?=[A-Z][a-z]|[0-9])/g
      , function(match, first){
          if (first) match = match[0].toUpperCase() + match.substr(1);
          return match + ' ';
          }
       )
   }

Probado aquí [JSFiddle, no library. No probé IE]; Debería ser bastante estable.

SamGoody
fuente
0

Si no le interesan los navegadores más antiguos (o no le importa usar una función de reducción de reserva para ellos), esto puede dividir incluso cadenas como 'xmlHTTPRequest' (pero ciertamente no puede hacerlo 'XMLHTTPRequest').

function splitCamelCase(str) {
        return str.split(/(?=[A-Z])/)
                  .reduce(function(p, c, i) {
                    if (c.length === 1) {
                        if (i === 0) {
                            p.push(c);
                        } else {
                            var last = p.pop(), ending = last.slice(-1);
                            if (ending === ending.toLowerCase()) {
                                p.push(last);
                                p.push(c);
                            } else {
                                p.push(last + c);
                            }
                        }
                    } else {
                        p.push(c.charAt(0).toUpperCase() + c.slice(1));
                    }
                    return p;
                  }, [])
                  .join(' ');
}
Daniel Fernández Espinoza
fuente
0

Mi version

function camelToSpace (txt) {
  return txt
    .replace(/([^A-Z]*)([A-Z]*)([A-Z])([^A-Z]*)/g, '$1 $2 $3$4')
    .replace(/ +/g, ' ')
}
camelToSpace("camelToSpaceWithTLAStuff") //=> "camel To Space With TLA Stuff"
pykiss
fuente
Apliqué esta función en bucle en 3000 líneas, y obtuve esos espacios delante de cada línea que comienza con mayúscula
Dominik Domanski
0

Prueba esta solución aquí:

var value = "myCamelCaseText";
var newStr = '';
for (var i = 0; i < value.length; i++) {
  if (value.charAt(i) === value.charAt(i).toUpperCase()) {
    newStr = newStr + ' ' + value.charAt(i)
  } else {
    (i == 0) ? (newStr += value.charAt(i).toUpperCase()) : (newStr += value.charAt(i));
  }
}
return newStr;
M3ghana
fuente
-5

No es una expresión regular, pero es útil para conocer técnicas simples y antiguas como esta:

var origString = "thisString";
var newString = origString.charAt(0).toUpperCase() + origString.substring(1);
robar
fuente
55
no, la pregunta es "thisString" a "This String" (con un espacio) no "ThisString"
Pete Kirkham
@rob ¿Cómo poner un espacio entre "esto" y "Cadena"?
ThunderBird