JavaScript RegEx: formatta la stringa con lunghezza dinamica per bloccare il formato

Aug 31 2020

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

2 anubhava Aug 31 2020 at 15:05

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
3 T.J.Crowder Aug 31 2020 at 15:08

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("");
2 WiktorStribiżew Aug 31 2020 at 15:09

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ù