The following RegEx formats given string to following output block pattern:
123 456 78 90 (= 3 digits 3 digits 2 digits 2 digits )
RegEx:
Using modern Javascript lookbehind that allows dynamic length assertion, you can use this regex to match:
/(?<=^(?:\d{6}(?:\d{2})*|(?:\d{3}){1,2}))(?=\d+$)/g
Just replace that with a single space i.e. " "
RegEx Demo
Lookbehind:
(?<=
: Start assertion
^(?:\d{6}(?:\d{2})*
: Make sure we have 6 digits followed by 0 or more digits pair behind|
: OR(?:\d{3}){1,2})
: Make we have one or two sets of 3 digit sets behind)
: End assertionLookahead:
(?=\d+$)
: Make sure we have at least a digit aheadanubhava's and Wiktor's solutions are clever, but I don't think I'd use a regular expression to do it; the solutions feel too complex to maintain. (This is a judgement call.) Here's an approach that gets the individual digits and inserts spaces after the third digit and after every subsequent digit whose index position is an odd number:
result = [...str].map((d, i) => d + (i === 2 || (i >= 5 && i % 2 === 1) ? " " : "")).join("");
Live Example:
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");
}
Here's a version that works in ES5-only environments:
result = str.split("").map(function(d, i) {
return d + (i === 2 || (i >= 5 && i % 2 === 1) ? " " : "");
}).join("");
You can use
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>
The ^(\d{3})(\d{1,3})?(\d{1,2})?(\d{1,2})?$
regex will perform live formatting together with the callback function used as the replacement argument. The first three digits are obligatory, the second, third and fourth blocks are optional, but contain at least one digit. Spaces are only added if there is at least one digit in the block. The number is reformatted each time the number is edited:
.replace(/\s+/g,'')
removes the added spaces.replace(/^(\d{10}).*/, '$1')
keeps just the first ten digits if there are more