JavaScript RegEx: string de formato com comprimento dinâmico para formato de bloco
Os seguintes formatos RegEx fornecem string para o seguinte padrão de bloco de saída:
123 456 78 90 (= 3 dígitos 3 dígitos 2 dígitos 2 dígitos )
RegEx:
string.replace(/^(\d{3})(\d{3})(\d{2})(\d{2})$/g, '$1 $2 $3 $4');
Este exemplo só funciona se a string de entrada fornecida corresponder ao comprimento exato de 10 dígitos.
Como posso ajustar o RegEx para trabalhar com cada comprimento de string?
- 1234 --> 123 4
- 1234567 --> 123 456 7
- 123456789 --> 123 456 78 9
- 1234567890123 --> 123 456 78 90 12 3
Background: Eu quero formatar a string de entrada de um campo de entrada de formulário diretamente, quando um usuário insere o número...
Respostas
Usando o lookbehind Javascript moderno que permite a afirmação de comprimento dinâmico, você pode usar este regex para corresponder:
/(?<=^(?:\d{6}(?:\d{2})*|(?:\d{3}){1,2}))(?=\d+$)/g
Basta substituir isso por um único espaço, ou seja" "
Demonstração RegEx
Olhar para trás:
(?<=: Iniciar afirmação^(?:\d{6}(?:\d{2})*: Certifique-se de que temos 6 dígitos seguidos por 0 ou mais dígitos pares atrás|: OU(?:\d{3}){1,2}): Faça com que tenhamos um ou dois conjuntos de conjuntos de 3 dígitos atrás
): Finalizar afirmação
Olhe para frente:
(?=\d+$): Certifique-se de que temos pelo menos um dígito à frente
as soluções de anubhava e Wiktor são inteligentes, mas não acho que usaria uma expressão regular para fazer isso; as soluções parecem complexas demais para serem mantidas. (Esta é uma chamada de julgamento.) Aqui está uma abordagem que obtém os dígitos individuais e insere espaços após o terceiro dígito e após cada dígito subsequente cuja posição do índice é um número ímpar:
result = [...str].map((d, i) => d + (i === 2 || (i >= 5 && i % 2 === 1) ? " " : "")).join("");
Exemplo ao vivo:
const tests = [
["1234", "123 4"],
["1234567", "123 456 7"],
["123456789", "123 456 78 9"],
["1234567890123", "123 456 78 90 12 3"],
];
function format(str) {
return [...str].map((d, i) => d + (i === 2 || (i >= 5 && i % 2 === 1) ? " " : "")).join("");
}
for (const [str, expected] of tests) {
const result = format(str);
console.log(`|${str}|`, "=>", `|${result}|`, result === expected ? "OK" : "*** ERROR");
}
Aqui está uma versão que funciona em ambientes somente ES5:
result = str.split("").map(function(d, i) {
return d + (i === 2 || (i >= 5 && i % 2 === 1) ? " " : "");
}).join("");
Você pode usar
const rx = /^(\d{3})(\d{1,3})?(\d{1,2})?(\d{1,2})?$/; $('body').on('input', '.info', function(e) {
this.value = this.value.replace(/\s+/g,'')
.replace(/^(\d{10}).*/, '$1') .replace(rx, (_,w,x,y,z) => z ? `${w} ${x} ${y} ${z}` : y ? `${w} ${x} ${y}` :
x ? `${w} ${x}` : w);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="info" maxlength=13>
O ^(\d{3})(\d{1,3})?(\d{1,2})?(\d{1,2})?$regex executará a formatação ao vivo junto com a função de retorno de chamada usada como argumento de substituição. Os três primeiros dígitos são obrigatórios, o segundo, terceiro e quarto blocos são opcionais, mas contêm pelo menos um dígito. Os espaços só são adicionados se houver pelo menos um dígito no bloco. O número é reformatado cada vez que o número é editado:
.replace(/\s+/g,'')remove os espaços adicionados.replace(/^(\d{10}).*/, '$1')mantém apenas os primeiros dez dígitos se houver mais