JavaScript RegEx: formatta la stringa con lunghezza dinamica per bloccare il formato
I seguenti formati RegEx hanno assegnato una stringa al seguente modello di blocco di output:
123 456 78 90 (= 3 cifre 3 cifre 2 cifre 2 cifre )
RegEx:
string.replace(/^(\d{3})(\d{3})(\d{2})(\d{2})$/g, '$1 $2 $3 $4');
Questo esempio funziona solo se la stringa di input specificata corrisponde alla lunghezza esatta di 10 cifre.
Come posso regolare RegEx in modo che funzioni con ogni lunghezza di stringa?
- 1234 --> 123 4
- 1234567 --> 123 456 7
- 123456789 --> 123 456 78 9
- 1234567890123 --> 123 456 78 90 12 3
Sfondo: voglio formattare direttamente la stringa di input di un campo di input del modulo, quando un utente inserisce il numero...
Risposte
Usando il moderno lookbehind di Javascript che consente l'asserzione dinamica della lunghezza, puoi usare questa espressione regolare per abbinare:
/(?<=^(?:\d{6}(?:\d{2})*|(?:\d{3}){1,2}))(?=\d+$)/g
Basta sostituirlo con un singolo spazio, ad es" "
Demo regolare
Guarda dietro:
(?<=: Inizia l'asserzione^(?:\d{6}(?:\d{2})*: assicurati di avere 6 cifre seguite da 0 o più coppie di cifre dietro|: O(?:\d{3}){1,2}): Fai in modo che abbiamo uno o due set di set di 3 cifre dietro
): Termina l'affermazione
Guarda avanti:
(?=\d+$): Assicurati di avere almeno una cifra avanti
Le soluzioni di anubhava e Wiktor sono intelligenti, ma non credo che userei un'espressione regolare per farlo; le soluzioni sembrano troppo complesse da mantenere. (Questa è una chiamata di giudizio.) Ecco un approccio che ottiene le singole cifre e inserisce spazi dopo la terza cifra e dopo ogni cifra successiva la cui posizione di indice è un numero dispari:
result = [...str].map((d, i) => d + (i === 2 || (i >= 5 && i % 2 === 1) ? " " : "")).join("");
Esempio dal 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");
}
Ecco una versione che funziona solo in ambienti ES5:
result = str.split("").map(function(d, i) {
return d + (i === 2 || (i >= 5 && i % 2 === 1) ? " " : "");
}).join("");
Puoi usare
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>
La ^(\d{3})(\d{1,3})?(\d{1,2})?(\d{1,2})?$regex eseguirà la formattazione live insieme alla funzione di callback utilizzata come argomento di sostituzione. Le prime tre cifre sono obbligatorie, il secondo, il terzo e il quarto blocco sono facoltativi, ma contengono almeno una cifra. Gli spazi vengono aggiunti solo se nel blocco è presente almeno una cifra. Il numero viene riformattato ogni volta che viene modificato il numero:
.replace(/\s+/g,'')rimuove gli spazi aggiunti.replace(/^(\d{10}).*/, '$1')mantiene solo le prime dieci cifre se ce ne sono di più