Converter camelCaseText em texto de maiúsculas e minúsculas

144

Como posso converter uma string como 'helloThere' ou 'HelloThere' para 'Hello There' em JavaScript?

HyderA
fonte
9
hmm .. qual é a sua saída esperada para o iLiveInTheUSA?
Wim
8
Eu vivo no U ... oh excremento! - Mas, no meu caso, tenho um conjunto limitado de strings e não existem strings que possam quebrar um conversor simples. Boa captura embora!
HyderA
Da mesma forma uSBPort deve resultar em "Porta USB"
signonsridhar
2
@wim: O iLiveInTheUSA deve ser o iLiveInTheUsa na notação correta de camelo, mas isso apresentaria problemas diferentes.
Konrad Höffner

Respostas:

187
var text = 'helloThereMister';
var result = text.replace( /([A-Z])/g, " $1" );
var finalResult = result.charAt(0).toUpperCase() + result.slice(1);
console.log(finalResult);

colocar em maiúscula a primeira letra - como um exemplo.

Observe o espaço em " $1".

EDIT: adicionado um exemplo de letras maiúsculas na primeira letra. Obviamente, caso a primeira letra já esteja em maiúscula - você teria um espaço livre para remover.

ZenMaster
fonte
1
Eu cavo o uso de espaços em text.replacechamadas de função de preenchimento, eu estive com 2+ argumentos com espaços para leitura demasiado
RKD
8
uSBPorts => Portas USB, não o que eu espero, eu quero uma Portas USB
signonsridhar
que tal escrever Non-GoogleChrome?
tim
107

Como alternativa, usando lodash :

lodash.startCase(str);

Exemplo:

_.startCase('helloThere');
// ➜ 'Hello There'

O Lodash é uma boa biblioteca para dar atalhos para muitas tarefas diárias do js. Existem muitas outras funções semelhantes de manipulação de strings, como camelCase, kebabCaseetc.

Wtower
fonte
Se você tentar hello world, a saída deve ser Hello There: Nesse caso, o loadash não será útil.
Abhishek Kumar
@AbhishekKumar startCase do lodash será convertido hello worldpara Hello World lodash.com/docs/4.17.15#upperFirst
user1696017
Você está certo mano. Por engano, escrevi hello therepara hello world.
Abhishek Kumar
2
Toda vez que penso "não há como o lodash fazer isso também", ele faz.
efru 3/03
Tenha cuidado a partir da v4, essa função remove caracteres especiais como ä e os converte em caracteres ASCII (a neste caso)
collerek 27/03
52

Eu tive um problema semelhante e lidei com isso assim:

stringValue.replace(/([A-Z]+)*([A-Z][a-z])/g, "$1 $2")

Para uma solução mais robusta:

stringValue.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, " $1")

http://jsfiddle.net/PeYYQ/

Entrada:

 helloThere 
 HelloThere 
 ILoveTheUSA
 iLoveTheUSA

Resultado:

 hello There 
 Hello There 
 I Love The USA
 i Love The USA
James Khoury
fonte
ele coloca um espaço extra no início
rehman hannad
4
Não é um caso de sentença, como solicitado pelo OP. A primeira letra deve ser maiúscula.
H Dog
Além disso, adiciona um espaço extra entre as palavras
Alacritas
34

Exemplo sem efeitos colaterais.

function camel2title(camelCase) {
  // no side-effects
  return camelCase
    // inject space before the upper case letters
    .replace(/([A-Z])/g, function(match) {
       return " " + match;
    })
    // replace first char with upper case
    .replace(/^./, function(match) {
      return match.toUpperCase();
    });
}

No ES6

const camel2title = (camelCase) => camelCase
  .replace(/([A-Z])/g, (match) => ` ${match}`)
  .replace(/^./, (match) => match.toUpperCase());
renevanderark
fonte
1
Sólido, +1 para o snippet es6.
BradStell
4
Para sua informação, isso adiciona espaço em branco extra ao início da frase.
Dale Zak
20

A melhor string que encontrei para testar as funções camel-case-title-case é esse exemplo ridiculamente absurdo, que testa muitos casos extremos. Que eu saiba, nenhuma das funções postadas anteriormente lida com isso corretamente :

ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D

Isso deve ser convertido para:

Para obter seu GED in time, uma música sobre os 26 ABCs é essencial, mas um cartão de identificação pessoal para o usuário 456 na sala 26A, que contém ABC 26 vezes não é tão fácil quanto 123 para C3PO ou R2D2 ou 2R2D

Se você deseja apenas uma função simples que lide com casos como o descrito acima (e mais casos do que muitas das respostas anteriores), aqui está o que escrevi. Esse código não é particularmente elegante ou rápido, mas é simples, compreensível e funciona.

Um exemplo executável on - line está no jsfiddle , ou você pode visualizar a saída do snippet abaixo no seu console:

// Take a single camel case string and convert it to a string of separate words (with spaces) at the camel-case boundaries.
// 
// E.g.:
var examples = [
    'ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D',
    //                                          --> To Get Your GED In Time A Song About The 26 ABCs Is Of The Essence But A Personal ID Card For User 456 In Room 26A Containing ABC 26 Times Is Not As Easy As 123 For C3PO Or R2D2 Or 2R2D
    'helloThere', //                              --> Hello There
    'HelloThere', //                              --> Hello There
    'ILoveTheUSA', //                             --> I Love The USA
    'iLoveTheUSA', //                             --> I Love The USA
    'DBHostCountry', //                           --> DB Host Country
    'SetSlot123ToInput456', //                    --> Set Slot 123 To Input 456
    'ILoveTheUSANetworkInTheUSA', //              --> I Love The USA Network In The USA
    'Limit_IOC_Duration', //                      --> Limit IOC Duration
    'This_is_a_Test_of_Network123_in_12_days', // --> This Is A Test Of Network 123 In 12 Days
    'ASongAboutTheABCsIsFunToSing', //            --> A Song About The ABCs Is Fun To Sing
    'CFDs', //                                    --> CFDs
    'DBSettings', //                              --> DB Settings
    'IWouldLove1Apple', //                        --> 1 Would Love 1 Apple
    'Employee22IsCool', //                        --> Employee 22 Is Cool
    'SubIDIn', //                                 --> Sub ID In
    'ConfigureCFDsImmediately', //                --> Configure CFDs Immediately
    'UseTakerLoginForOnBehalfOfSubIDInOrders', // --> Use Taker Login For On Behalf Of Sub ID In Orders
]

function camelCaseToTitleCase(in_camelCaseString) {
        var result = in_camelCaseString                         // "ToGetYourGEDInTimeASongAboutThe26ABCsIsOfTheEssenceButAPersonalIDCardForUser456InRoom26AContainingABC26TimesIsNotAsEasyAs123ForC3POOrR2D2Or2R2D"
            .replace(/([a-z])([A-Z][a-z])/g, "$1 $2")           // "To Get YourGEDIn TimeASong About The26ABCs IsOf The Essence ButAPersonalIDCard For User456In Room26AContainingABC26Times IsNot AsEasy As123ForC3POOrR2D2Or2R2D"
            .replace(/([A-Z][a-z])([A-Z])/g, "$1 $2")           // "To Get YourGEDIn TimeASong About The26ABCs Is Of The Essence ButAPersonalIDCard For User456In Room26AContainingABC26Times Is Not As Easy As123ForC3POOr R2D2Or2R2D"
            .replace(/([a-z])([A-Z]+[a-z])/g, "$1 $2")          // "To Get Your GEDIn Time ASong About The26ABCs Is Of The Essence But APersonal IDCard For User456In Room26AContainingABC26Times Is Not As Easy As123ForC3POOr R2D2Or2R2D"
            .replace(/([A-Z]+)([A-Z][a-z][a-z])/g, "$1 $2")     // "To Get Your GEDIn Time A Song About The26ABCs Is Of The Essence But A Personal ID Card For User456In Room26A ContainingABC26Times Is Not As Easy As123ForC3POOr R2D2Or2R2D"
            .replace(/([a-z]+)([A-Z0-9]+)/g, "$1 $2")           // "To Get Your GEDIn Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456In Room 26A Containing ABC26Times Is Not As Easy As 123For C3POOr R2D2Or 2R2D"
            
            // Note: the next regex includes a special case to exclude plurals of acronyms, e.g. "ABCs"
            .replace(/([A-Z]+)([A-Z][a-rt-z][a-z]*)/g, "$1 $2") // "To Get Your GED In Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456In Room 26A Containing ABC26Times Is Not As Easy As 123For C3PO Or R2D2Or 2R2D"
            .replace(/([0-9])([A-Z][a-z]+)/g, "$1 $2")          // "To Get Your GED In Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456In Room 26A Containing ABC 26Times Is Not As Easy As 123For C3PO Or R2D2Or 2R2D"  

            // Note: the next two regexes use {2,} instead of + to add space on phrases like Room26A and 26ABCs but not on phrases like R2D2 and C3PO"
            .replace(/([A-Z]{2,})([0-9]{2,})/g, "$1 $2")        // "To Get Your GED In Time A Song About The 26ABCs Is Of The Essence But A Personal ID Card For User 456 In Room 26A Containing ABC 26 Times Is Not As Easy As 123 For C3PO Or R2D2 Or 2R2D"
            .replace(/([0-9]{2,})([A-Z]{2,})/g, "$1 $2")        // "To Get Your GED In Time A Song About The 26 ABCs Is Of The Essence But A Personal ID Card For User 456 In Room 26A Containing ABC 26 Times Is Not As Easy As 123 For C3PO Or R2D2 Or 2R2D"
            .trim();


  // capitalize the first letter
  return result.charAt(0).toUpperCase() + result.slice(1);
}

examples.forEach(str => console.log(str, ' --> \n', camelCaseToTitleCase(str)));

Chris Kline
fonte
11

Com base em um dos exemplos acima, vim com isso:

const camelToTitle = (camelCase) => camelCase
  .replace(/([A-Z])/g, (match) => ` ${match}`)
  .replace(/^./, (match) => match.toUpperCase())
  .trim()

Funciona para mim porque é usado .trim()para lidar com o caso em que a primeira letra é maiúscula e você acaba com um espaço extra à esquerda.

Referência: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim

Anthony S.
fonte
10

Ok, estou alguns anos atrasado para o jogo, mas tive uma pergunta semelhante e queria criar uma solução de substituição única para cada entrada possível. Devo dar a maior parte do crédito a @ZenMaster neste tópico e a @Benjamin Udink ten Cate neste tópico. Aqui está o código:

var camelEdges = /([A-Z](?=[A-Z][a-z])|[^A-Z](?=[A-Z])|[a-zA-Z](?=[^a-zA-Z]))/g;
var textArray = ["lowercase",
                 "Class",
                 "MyClass",
                 "HTML",
                 "PDFLoader",
                 "AString",
                 "SimpleXMLParser",
                 "GL11Version",
                 "99Bottles",
                 "May5",
                 "BFG9000"];
var text;
var resultArray = [];
for (var i = 0; i < a.length; i++){
    text = a[i];
    text = text.replace(camelEdges,'$1 ');
    text = text.charAt(0).toUpperCase() + text.slice(1);
    resultArray.push(text);
}

Possui três cláusulas, todas usando lookahead para impedir que o mecanismo regex consuma muitos caracteres:

  1. [A-Z](?=[A-Z][a-z])procura uma letra maiúscula seguida de uma maiúscula e minúscula. Isso é para terminar acrônimos como EUA.
  2. [^A-Z](?=[A-Z])procura por uma letra maiúscula seguida por uma letra maiúscula. Isso termina palavras como myWord e símbolos como 99Bottles.
  3. [a-zA-Z](?=[^a-zA-Z])procura por uma letra seguida por uma não-letra. Isso termina palavras antes de símbolos como BFG9000.

Esta pergunta estava no topo dos meus resultados de pesquisa, por isso espero poder poupar outras pessoas algum tempo!

Christopher Smith
fonte
9

Aqui está a minha versão. Ele adiciona um espaço antes de cada letra em inglês do UpperCase que vem depois de uma letra em minúscula e também coloca a primeira letra em maiúscula, se necessário:

Por exemplo:
thisIsCamelCase -> Este é o caso de camelo
this IsCamelCase -> Este é o caso de camelo
thisIsCamelCase123 -> Este é o caso de camelo123

  function camelCaseToTitleCase(camelCase){
    if (camelCase == null || camelCase == "") {
      return camelCase;
    }

    camelCase = camelCase.trim();
    var newText = "";
    for (var i = 0; i < camelCase.length; i++) {
      if (/[A-Z]/.test(camelCase[i])
          && i != 0
          && /[a-z]/.test(camelCase[i-1])) {
        newText += " ";
      }
      if (i == 0 && /[a-z]/.test(camelCase[i]))
      {
        newText += camelCase[i].toUpperCase();
      } else {
        newText += camelCase[i];
      }
    }

    return newText;
  }
asafd
fonte
6

Esta implementação leva em maiúsculas e números consecutivos em consideração.

function camelToTitleCase(str) {
  return str
    .replace(/[0-9]{2,}/g, match => ` ${match} `)
    .replace(/[^A-Z0-9][A-Z]/g, match => `${match[0]} ${match[1]}`)
    .replace(/[A-Z][A-Z][^A-Z0-9]/g, match => `${match[0]} ${match[1]}${match[2]}`)
    .replace(/[ ]{2,}/g, match => ' ')
    .replace(/\s./g, match => match.toUpperCase())
    .replace(/^./, match => match.toUpperCase())
    .trim();
}

// ----------------------------------------------------- //

var testSet = [
    'camelCase',
    'camelTOPCase',
    'aP2PConnection',
    'superSimpleExample',
    'aGoodIPAddress',
    'goodNumber90text',
    'bad132Number90text',
];

testSet.forEach(function(item) {
    console.log(item, '->', camelToTitleCase(item));
});

Saída esperada:

camelCase -> Camel Case
camelTOPCase -> Camel TOP Case
aP2PConnection -> A P2P Connection
superSimpleExample -> Super Simple Example
aGoodIPAddress -> A Good IP Address
goodNumber90text -> Good Number 90 Text
bad132Number90text -> Bad 132 Number 90 Text
Dipu
fonte
Eu usaria a resposta de Chris Kline, que acomoda strings como "Endereço IP" (onde essa função a transforma em "Endereço IP")
John Hamm
@JohnHamm Sua entrada é "Endereço IP", certo? Não é um caso de camelo! Leia sobre o caso de camel aqui: en.wikipedia.org/wiki/Camel_case Não coloque espaço entre e insira apenas "IPAddress". Esta função funciona bem.
Dipu 25/01
3

Você pode usar uma função como esta:

function fixStr(str) {
    var out = str.replace(/^\s*/, "");  // strip leading spaces
    out = out.replace(/^[a-z]|[^\s][A-Z]/g, function(str, offset) {
        if (offset == 0) {
            return(str.toUpperCase());
        } else {
            return(str.substr(0,1) + " " + str.substr(1).toUpperCase());
        }
    });
    return(out);
}

"hello World" ==> "Hello World"
"HelloWorld" ==> "Hello World"
"FunInTheSun" ==? "Fun In The Sun"

Código com várias sequências de teste aqui: http://jsfiddle.net/jfriend00/FWLuV/ .

Versão alternativa que mantém os espaços principais aqui: http://jsfiddle.net/jfriend00/Uy2ac/ .

jfriend00
fonte
Sei que não era um requisito na pergunta, mas sua solução não funciona " helloWorld", por exemplo.
ZenMaster 29/08
Sim, esse é um novo requisito. Eu tentei fazer exatamente o que você originalmente pediu. De qualquer forma, o caminho mais curto é fácil de separar os espaços principais, se você não precisar deles de qualquer maneira. Se você queria que eles fossem deixados no lugar, isso também poderia ser feito.
precisa saber é o seguinte
Aqui está um jsFiddle que mostra um método que funciona com o novo requisito do "helloWorld" e mantém o espaço inicial (se você quiser): jsfiddle.net/jfriend00/Uy2ac .
precisa saber é o seguinte
Agradável. Eu me pergunto sobre o desempenho disso, no entanto. A função manipuladora será chamada em todas as partidas, não é?
ZenMaster 29/08
Se você estiver fazendo um zilhão disso em uma configuração sensível ao desempenho, seria necessário fazer alguns testes jsperf em vários navegadores para ver qual seria a solução mais rápida. Ligar para um retorno de chamada não é grande coisa. Expressões regulares, de qualquer tipo, raramente são a solução mais rápida versus o código de finalidade especial, mas economizam muito código (e geralmente alguns bugs), portanto, muitas vezes são a escolha desejada. Depende de suas necessidades.
jfriend00
3

tente esta biblioteca

http://sugarjs.com/api/String/titleize

'man from the boondocks'.titleize()>"Man from the Boondocks"
'x-men: the last stand'.titleize()>"X Men: The Last Stand"
'TheManWithoutAPast'.titleize()>"The Man Without a Past"
'raiders_of_the_lost_ark'.titleize()>"Raiders of the Lost Ark"
Barno
fonte
2

Nenhuma das respostas acima funcionou perfeitamente para mim, então teve que vir com a própria bicicleta:

function camelCaseToTitle(camelCase) {
    if (!camelCase) {
        return '';
    }

    var pascalCase = camelCase.charAt(0).toUpperCase() + camelCase.substr(1);
    return pascalCase
        .replace(/([a-z])([A-Z])/g, '$1 $2')
        .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2')
        .replace(/([a-z])([0-9])/gi, '$1 $2')
        .replace(/([0-9])([a-z])/gi, '$1 $2');
}

Casos de teste:

null => ''
'' => ''
'simpleString' => 'Simple String'
'stringWithABBREVIATIONInside => 'String With ABBREVIATION Inside'
'stringWithNumber123' => 'String With Number 123'
'complexExampleWith123ABBR890Etc' => 'Complex Example With 123 ABBR 890 Etc'
Vitaliy Ulantikov
fonte
2

Isso funciona para mim, verifique isso

CamelcaseToWord ("MyName"); // retorna Meu nome

    function CamelcaseToWord(string){
      return string.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, " $1");
    }
Poorna Rao
fonte
1
Bem-vindo ao SO :) Adicione pelo menos uma linha explicativa ao seu código. Também verifique se é seu trabalho intelectual ou cite a (s) fonte (s).
Lorenz Lo Sauer
Você deve remover o espaço em um lat "$ 1". string.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, "$1");
Valeria Shpiner 22/04
2

Eu acho que isso pode ser feito apenas com o reg exp /([a-z]|[A-Z]+)([A-Z])/ge substituição "$1 $2".

ILoveTheUSADope -> Eu amo o narcótico dos EUA

Miguel Enrique León Figueras
fonte
Não exatamente, para string, QWERTYele retorna QWERT Y.
itachi
2

Se você lida com o Capital Camel Case, esse trecho pode ajudá-lo, mas também contém algumas especificações, para que você possa ter certeza de que ele corresponde ao seu caso.

export const fromCamelCaseToSentence = (word) =>
  word
    .replace(/([A-Z][a-z]+)/g, ' $1')
    .replace(/([A-Z]{2,})/g, ' $1')
    .replace(/\s{2,}/g, ' ')
    .trim();

E especificações:

describe('fromCamelCaseToSentence', () => {
 test('does not fall with a single word', () => {
   expect(fromCamelCaseToSentence('Approved')).toContain('Approved')
   expect(fromCamelCaseToSentence('MDA')).toContain('MDA')
 })

 test('does not fall with an empty string', () => {
   expect(fromCamelCaseToSentence('')).toContain('')
 })

 test('returns the separated by space words', () => {
   expect(fromCamelCaseToSentence('NotApprovedStatus')).toContain('Not Approved Status')
   expect(fromCamelCaseToSentence('GDBState')).toContain('GDB State')
   expect(fromCamelCaseToSentence('StatusDGG')).toContain('Status DGG')
 })
})
Purkhalo Alex
fonte
1

Não tentei a resposta de todos, mas as poucas soluções com as quais eu trabalhei não atendiam a todos os meus requisitos.

Consegui inventar algo que fez ...

export const jsObjToCSSString = (o={}) =>
    Object.keys(o)
          .map(key => ({ key, value: o[key] }))
          .map(({key, value}) =>
              ({
                key: key.replace( /([A-Z])/g, "-$1").toLowerCase(),
                value
              })
          )
          .reduce(
              (css, {key, value}) => 
                  `${css} ${key}: ${value}; `.trim(), 
              '')
Tabbyofjudah
fonte
1

Abaixo está o link que demonstra a sequência de caracteres de camelo para sentença usando regex.

Entrada

myCamelCaseSTRINGToSPLITDemo

Resultado

my Camel Case STRING To SPLIT Demo


Este é o regex para conversão de maiúsculas e minúsculas em texto de frase

(?=[A-Z][a-z])|([A-Z]+)([A-Z][a-rt-z][a-z]\*)

com $1 $2como subscrição.

Clique para ver a conversão em regex

Rahul
fonte
Forneça o conteúdo relevante do seu link no corpo da sua resposta.
Grant Miller
1

Entrada javaScript

Script Java de Saída

   var text = 'javaScript';
    text.replace(/([a-z])([A-Z][a-z])/g, "$1 $2").charAt(0).toUpperCase()+text.slice(1).replace(/([a-z])([A-Z][a-z])/g, "$1 $2");
Manas
fonte
1

Mais uma solução baseada em RegEx.

respace(str) {
  const regex = /([A-Z])(?=[A-Z][a-z])|([a-z])(?=[A-Z])/g;
  return str.replace(regex, '$& ');
}

Explicação

O RegEx acima consiste em duas partes semelhantes separadas pelo operador OR . A primeira metade:

  1. ([A-Z]) - corresponde a letras maiúsculas ...
  2. (?=[A-Z][a-z]) - seguido por uma sequência de letras maiúsculas e minúsculas.

Quando aplicado à sequência FOo , corresponde efetivamente à sua letra F.

Ou o segundo cenário:

  1. ([a-z]) - corresponde a letras minúsculas ...
  2. (?=[A-Z]) - seguido por uma letra maiúscula.

Quando aplicado à sequência barFoo , corresponde efetivamente à sua letra r .

Quando todos os candidatos a substituição foram encontrados, a última coisa a fazer é substituí-los pela mesma letra, mas com um caractere de espaço adicional. Para isso, podemos usar '$& 'como um substituto, e ele será resolvido para uma substring correspondente, seguida por um caractere de espaço.

Exemplo

const regex = /([A-Z])(?=[A-Z][a-z])|([a-z])(?=[A-Z])/g
const testWords = ['ACoolExample', 'fooBar', 'INAndOUT', 'QWERTY', 'fooBBar']

testWords.map(w => w.replace(regex, '$& '))
->(5) ["A Cool Example", "foo Bar", "IN And OUT", "QWERTY", "foo B Bar"]
itachi
fonte
-1

Adicionando mais uma solução ES6 que eu mais gostei depois de não estar feliz com algumas reflexões acima.

https://codepen.io/902Labs/pen/mxdxRv?editors=0010#0

const camelize = (str) => str
    .split(' ')
    .map(([first, ...theRest]) => (
        `${first.toUpperCase()}${theRest.join('').toLowerCase()}`)
    )
    .join(' ');
user169251
fonte