Comment convertir «camelCase» en «Camel Case»?

174

J'ai essayé d'obtenir une commande JavaScript regex pour transformer quelque chose comme "thisString"en "This String"mais le plus proche que j'ai obtenu est de remplacer une lettre, ce qui donne quelque chose comme "Thi String"ou "This tring". Des idées?

Pour clarifier, je peux gérer la simplicité de la capitalisation d'une lettre, je ne suis tout simplement pas aussi fort avec RegEx, et la division "somethingLikeThis"en "something Like This"est là où j'ai des problèmes.

Un sorcier l'a fait
la source
6
Comment est-ce un double de cela? Tout ce que cela fait est de mettre en majuscule le premier caractère d'une chaîne, rien de proche de ce que je veux faire.
Un sorcier l'a fait
Hmm ce n'est pas une dupe de la question, mais le résultat pourrait être le même. Ou n'est-ce pas ce que vous vouliez faire? Elaborer plus?
superfro
Pour la pratique des regex, je suggère RegExr ou Expresso de tester et de regarder toutes les questions regex sur SO et d'essayer d'y répondre. Les regex ne sont pas la chose la plus simple au monde, mais rappelez-vous simplement que si votre regex vous déroute, alors divisez-la et travaillez en morceaux.
josh.trow

Réponses:

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

affiche

This String Is Good

Vincent Robert
la source
1
Bon homme, je l'ai divisé. Rappelez - vous des conseils de Bobince: stackoverflow.com/questions/1732348/...
josh.trow
Êtes-vous sûr que cela est compatible avec IE? Je viens d'essayer dans IETester7 et j'ai une erreur.
strongriley
3
Ajout également: si vous avez un acronyme tout en majuscules que vous voulez garder ensemble, vous pouvez changer la première expression régulière en "/ ([AZ] [az]) /"
jackfrster
2
"This" -> "This" (espace de préfixe indésirable). Peut-être le changer en: str.slice (0, 1) .toUpperCase () + str.slice (1) .replace (/ ([AZ]) / g, '$ 1')
Mark Vayngrib
1
@ColdCerberus Vous pouvez utiliser: str.replace(/((?<!^)[A-Z](?![A-Z]))(?=\S)/g, ' $1').replace(/^./, s => s.toUpperCase() );Il se convertira userIDen User ID, et il se convertira même userIDFieldenUser ID Field
Eugene Mala
87

J'avais un intérêt vide pour cela, en particulier dans la gestion des séquences de majuscules, comme dans xmlHTTPRequest. Les fonctions listées produiraient "Xml HTTP Request" ou "Xml HTTPRequest", la mienne produirait "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(); })
}

Il y a aussi une version String.prototype dans un résumé .

Matt Wiebe
la source
La même chose peut être obtenue avec 2 appels de remplacement:str.replace(/((?<!^)[A-Z](?![A-Z]))(?=\S)/g, ' $1').replace(/^./, s => s.toUpperCase() )
Eugene Mala
22

Cela peut être fait de manière concise avec regex lookahead ( démo en direct ):

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

(Je pensais que le gdrapeau (global) était nécessaire, mais curieusement, ce n'est pas dans ce cas particulier.)

L'utilisation de lookahead avec splitgarantit que la lettre majuscule correspondante n'est pas consommée et évite de traiter un espace de début si UpperCamelCase est quelque chose que vous devez traiter. Pour mettre en majuscule la première lettre de chacun, vous pouvez utiliser:

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

La mapméthode de tableau est une fonctionnalité ES5, mais vous pouvez toujours l'utiliser dans les navigateurs plus anciens avec du code de MDC . Vous pouvez également parcourir les éléments du tableau à l'aide d'une forboucle.

Veuillez vous lever
la source
La première fonction le divise, mais pas PascalCase le premier mot. La deuxième fonction échoue sur un cas non camelCased. (par exemple: 'id')
Dementic
16

Je pense que cela devrait être capable de gérer des caractères majuscules consécutifs ainsi que de simples camelCase.

Par exemple: someVariable => someVariable, mais ABCCode! = ABC Code.

L'expression régulière ci-dessous fonctionne sur votre exemple, mais aussi sur l'exemple courant de représentation des abréviations dans 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"

Vous pouvez également ajuster comme ci-dessus pour mettre en majuscule le premier caractère.

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

spacecamel ('quelque chose comme ça')

// valeur renvoyée: quelque chose comme ça

Kennebec
la source
1
Joli! c'est exactement ce dont j'avais besoin que je voulais diviser par exemple: DiscoveryChannel et HBO d'autres réponses m'ont donné Discovery Channel et HBO, mais votre réponse a fait l'affaire pour moi car HBO est restée intacte merci!
AJS
8

Lodash gère cela bien avec_.startCase()

Lawrence Chang
la source
4

Une solution qui gère également les nombres:

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

Testé ici [JSFiddle, pas de bibliothèque. Non essayé IE]; devrait être assez stable.

SamGoody
la source
0

Si vous ne vous souciez pas des navigateurs plus anciens (ou si cela ne vous dérange pas d'utiliser une fonction de réduction de secours pour eux), cela peut même diviser des chaînes comme 'xmlHTTPRequest' (mais certainement les goûts de 'XMLHTTPRequest' ne le peuvent pas).

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
la source
0

Ma 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
la source
J'ai appliqué cette fonction en boucle sur 3000 lignes et j'ai obtenu ces espaces devant chaque ligne commençant par une majuscule
Dominik Domanski
0

Essayez cette solution ici -

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
la source
-5

Pas de regex, mais utile pour connaître des techniques simples et anciennes comme celle-ci:

var origString = "thisString";
var newString = origString.charAt(0).toUpperCase() + origString.substring(1);
Rob
la source
5
non, la question est "thisString" à "This String" (avec un espace) et non "ThisString"
Pete Kirkham
@rob Comment mettez-vous un espace entre "this" et "String"?
ThunderBird