Como converter "camelCase" para "Camel Case"?

174

Eu tenho tentado obter um comando regex JavaScript para transformar algo como "thisString"em "This String", mas o mais próximo que eu comecei está substituindo uma carta, resultando em algo como "Thi String"ou "This tring". Alguma ideia?

Para esclarecer eu posso lidar com a simplicidade de capitalizar uma carta, eu não sou tão forte com RegEx, e dividir "somethingLikeThis"em "something Like This"é onde eu estou tendo problemas.

Um assistente fez isso
fonte
6
Como isso é uma duplicata disso? Tudo o que faz é colocar o primeiro caractere em maiúscula em uma string, nada próximo do que eu quero fazer.
A Wizard Did It
Hmm, não é um engano da questão, mas o resultado pode ser o mesmo. Ou não é isso que você queria fazer? Elaborar mais?
superfro
Para a prática de regex, sugiro que o RegExr ou o Expresso faça um teste e observe todas as perguntas sobre regex no SO e tente respondê-las. Regexs não são a coisa mais simples do mundo, mas lembre-se de que, se o seu regex estiver confuso, VOCÊ o dividirá e trabalhará em pedaços.
josh.trow

Respostas:

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

exibe

This String Is Good

Vincent Robert
fonte
1
Bom homem, dividindo tudo. Lembre-se do conselho de Bobince: stackoverflow.com/questions/1732348/…
josh.trow
Você tem certeza de que isso é compatível com o IE? Tentei apenas no IETester7 e recebi um erro.
strongriley
3
Também adicionando: se você tem um acrônimo todos os tampões que você deseja manter juntos, você pode mudar o primeiro regex para "/ ([AZ] [az]) /"
jackfrster
2
"This" -> "This" (espaço de prefixo indesejado). Talvez mude para: str.slice (0, 1) .toUpperCase () + str.slice (1) .replace (/ ([AZ]) / g, '$ 1')
Mark Vayngrib
1
@ColdCerberus Você pode usar: str.replace(/((?<!^)[A-Z](?![A-Z]))(?=\S)/g, ' $1').replace(/^./, s => s.toUpperCase() );Ele se converterá userIDem User ID, e até se converterá userIDFieldem #User ID Field
Eugene Mala
87

Eu tinha um interesse inativo nisso, particularmente no manuseio de seqüências de capitais, como no xmlHTTPRequest. As funções listadas produziriam "Xml HTTP Request" ou "Xml HTTPRequest", a minha produz "Xml HTTP Request".

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

Há também uma versão String.prototype em uma essência .

Matt Wiebe
fonte
O mesmo pode ser alcançado com 2 chamadas de substituição:str.replace(/((?<!^)[A-Z](?![A-Z]))(?=\S)/g, ' $1').replace(/^./, s => s.toUpperCase() )
Eugene Mala
22

Isso pode ser feito de forma concisa com o regex lookahead ( demonstração ao vivo ):

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

(Eu pensei que a gbandeira (global) era necessária, mas por incrível que pareça, não é nesse caso em particular.)

O uso de lookahead with splitgarante que a letra maiúscula correspondente não seja consumida e evita lidar com um espaço à esquerda se UpperCamelCase for algo com o qual você precisa lidar. Para colocar em maiúscula a primeira letra de cada uma, você pode usar:

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

O mapmétodo array é um recurso do ES5, mas você ainda pode usá-lo em navegadores mais antigos com algum código do MDC . Como alternativa, você pode iterar sobre os elementos da matriz usando um forloop.

PleaseStand
fonte
A primeira função a divide, mas não PascalCase a primeira palavra. A segunda função falha em um gabinete camelCased nenhum. (por exemplo: 'id')
Dementic 20/04/19
16

Eu acho que isso deve ser capaz de lidar com caracteres maiúsculos consecutivos, bem como camelCase simples.

Por exemplo: someVariable => someVariable, mas ABCCode! = Código ABC.

O regex abaixo funciona no seu exemplo, mas também no exemplo comum de representação de abreviações no 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"

Você também pode ajustar como acima para colocar em maiúscula o primeiro caractere.

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

spacecamel ('somethingLikeThis')

// valor retornado: algo como isto

Kennebec
fonte
1
Agradável! isto é exatamente o que eu precisava que eu queria dividir, por exemplo: DiscoveryChannel e HBO outras respostas me deram o Discovery Channel e a HBO, mas sua resposta fez o truque para mim, pois a HBO permaneceu intacta, obrigado!
AJS
8

A Lodash lida bem com isso_.startCase()

Lawrence Chang
fonte
4

Uma solução que também lida com 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 + ' ';
          }
       )
   }

Testado aqui [JSFiddle, nenhuma biblioteca. Não tentei IE]; deve ser bem estável.

SamGoody
fonte
0

Se você não se importa com navegadores antigos (ou não se importa em usar uma função de redução de fallback para eles), isso pode dividir seqüências pares como 'xmlHTTPRequest' (mas certamente os gostos de 'XMLHTTPRequest' não podem).

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
fonte
0

Minha versão

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
fonte
Eu apliquei essa função no circuito em 3000 linhas, e tem aqueles espaços na frente de cada linha que começa com o capital
Dominik Domanski
0

Experimente esta solução aqui -

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
fonte
-5

Não é regex, mas é útil conhecer técnicas simples e antigas como esta:

var origString = "thisString";
var newString = origString.charAt(0).toUpperCase() + origString.substring(1);
roubar
fonte
5
não, a questão é "thisString" para "Este String" (com um espaço) não "ThisString"
Pete Kirkham
@rob Como você coloca um espaço entre "this" e "String"?
ThunderBird