Dividir uma string em uma letra maiúscula ou em números

9

Eu estava tentando fazer um pipe no texto datilografado que dividisse uma string PascalCase, mas seria bom se isso também fosse dividido em dígitos. Eu também gostaria que fosse dividido em maiúsculas consecutivas. Eu tenho esse pipe, que funciona muito bem, exceto que funciona apenas no Chrome e não no Firefox, evidentemente, apenas o Chrome oferece suporte ao visual. Como conseguir isso sem olhar para trás?

transform(value: string): string {
        let extracted = '';
        if (!value) {
            return extracted;
        }

        const regExSplit = value
            .split(new RegExp('(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[0-9])(?=[A-Z][a-z])|(?<=[a-zA-Z])(?=[0-9])'));
        for (let i = 0; i < regExSplit.length; i++) {
            if (i !== regExSplit.length - 1) {
                extracted += `${regExSplit[i]} `;
            } else {
                extracted += regExSplit[i];
            }
        }

        return extracted;
    }

Por exemplo, uma string ANet15Amountdeve ser transformada em A Net 15 Amount. Esse regex acima também dividiria uma string camelCase, mas isso não é necessário considerar.

develmatik
fonte
.replace(/([A-Z]|\d+)/g, " $1").trim();
Ibrahim mahrir
2
@ibrahimmahrir (?!^)([A-Z]|\d+)evita o primeiro espaço e não precisa de corte.
Ctwheels #

Respostas:

6

Que tal corresponder por um padrão mais básico como esse e juntar - se ao espaço.

let str = `ANet15Amount`;

let camel = str.match(/[A-Z]+(?![a-z])|[A-Z]?[a-z]+|\d+/g).join(' ');

console.log(camel);

Primeiro pensei em simplesmente, [A-Z][a-z]*|\d+mas isso iria entrar, por exemplo, ABCDefg123no A B C Defg 123qual seria diferente trabalhar para sua função atual, que se transforma em ABC Defg 123.

Ainda há uma pequena diferença. Teus transforma A1B2a A 1B 2e esta para A 1 B 2onde eu acho que este seria mais preciso, não é.

bolha bobble
fonte
11
Brilhante, passei em todos os meus casos de teste. Eu concordo, o seu é mais preciso. Eu realmente gostei disso!
develmatik
@develmatik Ainda bem que funciona como desejado, acabei de ler sobre as diferenças de camelo PascalCase :)
Bubble Bobble
3

Basta substituir qualquer letra maiúscula [A-Z]ou qualquer sequência de dígitos \d+por um espaço mais o que acabamos de corresponder " $1". Ignoramos a primeira letra para que nenhum espaço seja adicionado no início da string resultante, adicionando um lookahead negativo no início da string (?!^):

// ...

return value.replace(/(?!^)([A-Z]|\d+)/g, " $1");

Exemplo:

ibrahim mahrir
fonte
2

Tentar [A-Z]?[a-z]+|[A-Z]|[0-9]+

  • 0 ou 1 letra maiúscula diretamente seguida por 1 ou mais letras minúsculas
  • ou 1 letra maiúscula
  • ou 1 ou mais dígitos

Teste no gerador: https://regex101.com/r/uBO0P5/1

Tony
fonte
2

Eu acho que depende das convenções da string que podem aumentar a complexidade

// here 'TIMES' & 'with' are seperated (example 2)
const str = 'SplittingStringsIsFunTimesA100000aaaTIMESwithFollowUp';

// here 'TIMES' & 'With' are seperated (exmpaple 3)
const str2 = 'SplittingStringsIsFunTimesA100000aaaTIMESWithCAPITAL5FollowUp';


// 1. USING REGEX - MATCH
console.log(
  '1. USING REGEX:\n',
  str
  .match(/(\d+|[a-z]+|[A-Z][a-z]*)/g)
  .join(' ')
);


// 2. USING REGEX - MATCH (KEEP ALL CAPITAL CHARS)
console.log(
  '2. USING REGEX (GROUP ALL):\n',
  str
  .match(/(\d+|[a-z]+|([A-Z]([A-Z]+|[a-z]*)))/g)
  .join(' ')
);

// 3. USING REGEX - MATCH (KEEP CAPITAL CHARS BUT LAST)
console.log(
  '3. USING REGEX (GROUP BUT LAST):\n',
  str2
  .match(/(\d+|[a-z]+|([A-Z]([a-z]+|([A-Z]+(?![a-z]))?)))/g)
  .join(' ')
);


// 4. USING SPLIT - FILTER
console.log(
  '4. USING SPLIT:\n',
  str2
  .split(/(\d+|[A-Z][a-z]*)/)
  .filter(v => v !== '')
  .join(' ')
);

1O1
fonte