102

I have a string: "The quick brown fox jumps over the lazy dogs."

I want to use JavaScript (possibly with jQuery) to insert a character every n characters. For example I want to call:

var s = "The quick brown fox jumps over the lazy dogs.";
var new_s = UpdateString("$",5);
// new_s should equal "The q$uick $brown$ fox $jumps$ over$ the $lazy $dogs.$"

The goal is to use this function to insert &shy into long strings to allow them to wrap.

Maybe someone knows of a better way?

someone
  • 358
  • 1
  • 14
brendan
  • 29,308
  • 20
  • 68
  • 109
  • You're better off letting the browser wrap text. Do you have long sentences like you used for your example above, or long words? – Dan Herbert Nov 20 '09 at 20:10
  • 1
    The browser won't wrap within a word, I have long words like "ThisIsAStupidLabelThatOneOfMyUsersWillTryToMakeInMyApplication" – brendan Nov 20 '09 at 20:15
  • Wouldn't a server side solution to break words into a maximum of n characters would be better? – Pool Nov 20 '09 at 20:19
  • Possibly, but a client side solution is more easily implemented for my current predicament. – brendan Nov 20 '09 at 20:26

9 Answers9

213

With regex

"The quick brown fox jumps over the lazy dogs.".replace(/(.{5})/g,"$1$")

The q$uick $brown$ fox $jumps$ over$ the $lazy $dogs.$
starball
  • 20,030
  • 7
  • 43
  • 238
YOU
  • 120,166
  • 34
  • 186
  • 219
  • 13
    Damn it! Nice regex-fu there. BTW is the last `$` needed in the replacement string? – Crescent Fresh Nov 20 '09 at 20:25
  • 3
    The last **$** in the replacement string is not needed, you can put what ever you want to put at the 5 space interval here, like **
    ** for instance.
    – skymook May 17 '11 at 16:42
  • 8
    I arrived at `"string".replace(/.{5}/g, "$&" + "
    ");`. The concatenation at the end is just to make it easier to read. `$&` in the replacement matches the matched string, so no grouping is required.
    – matpie Mar 19 '14 at 22:49
  • 3
    How would that work when counting from the end of the string? – philk Jun 07 '14 at 12:29
  • Great. One important note is if the string contains line breaks, this will start counting from zero at the start of every line, since `.` doesn't match `\n` or `\r`. This is perfect for folding long lines of plaintext, but may not be desirable with web content. To include newlines in the match use `/[\s\S]{5}/g`. – Lack Jul 21 '14 at 07:07
  • @philk Regex really only works left-to-right. You can, in some cases, use replace within a loop to effectively go right-to-left: see [this question](http://stackoverflow.com/questions/16835754/regex-reads-from-right-to-left). But this won't work if the inserted character already occurs in the string. It's much easier to adapt Crescent Fresh's answer to count backward. – Lack Jul 21 '14 at 07:34
  • Best answer, although the `$` used for the inserted character is a bit confusing. – DevonDahon Nov 23 '20 at 16:56
  • How to only add a "-" after 3 characters and then do a break without continuing to other characters? – Sohaib Dec 10 '20 at 12:37
  • can someone provide same functionality using php – Azhar Uddin Sheikh Jan 11 '22 at 08:22
84
function chunk(str, n) {
    var ret = [];
    var i;
    var len;

    for(i = 0, len = str.length; i < len; i += n) {
       ret.push(str.substr(i, n))
    }

    return ret
};

chunk("The quick brown fox jumps over the lazy dogs.", 5).join('$');
// "The q$uick $brown$ fox $jumps$ over$ the $lazy $dogs."
coolaj86
  • 74,004
  • 20
  • 105
  • 125
Crescent Fresh
  • 115,249
  • 25
  • 154
  • 140
  • @Andy E: heh, they're optional just before a closing `}`. I don't even realize I do that anymore. It's born from a "must conserve every byte" mentality from years before js compressors became standard ;) – Crescent Fresh Nov 20 '09 at 23:05
  • `String.split("")` & `Array.form()` –  Aug 30 '17 at 02:47
  • regex & string.split() & array.form() & slice() & map() & JSON.parse() –  Aug 30 '17 at 02:58
  • 1
    A word of caution for anyone relying on this answer in 2023: `substr()` is a legacy function (not fully deprecated yet) and should be avoided where possible: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr – Bradley Mar 26 '23 at 10:53
60

Keep it simple

  var str = "123456789";
  var parts = str.match(/.{1,3}/g);
  var new_value = parts.join("-"); //returns 123-456-789
Kareem
  • 5,068
  • 44
  • 38
8
let s = 'The quick brown fox jumps over the lazy dogs.';
s.split('').reduce((a, e, i)=> a + e + (i % 5 === 4 ? '$' : ''), '');

Explain: split('') turns a string into an array. Now we want to turn the array back to one single string. Reduce is perfect in this scenario. Array's reduce function takes 3 parameters, first is the accumulator, second is the iterated element, and the third is the index. Since the array index is 0 based, to insert after 5th, we are looking at index i%5 === 4.

g.sui
  • 1,550
  • 3
  • 15
  • 20
  • 1
    Thank you a lot for this code. Here is the code, based on yours, I use to add a space every 2 chars for a phone number input (keyup event) : ~~~ $(this).val( $(this).val().replace(/ /g,"").split('').reduce((a,e,i) => a + e + (i % 2 === 1 ? ' ': ''),'').trim() ); ~~~ – Mystral Apr 17 '20 at 10:32
3
var str="ABCDEFGHIJKLMNOPQR";
function formatStr(str, n) {
   var a = [], start=0;
   while(start<str.length) {
      a.push(str.slice(start, start+n));
      start+=n;
   }
   console.log(a.join(" "));
}
formatStr(str,3);
Kanti
  • 41
  • 4
1
function addItemEvery (str, item, every){
  for(let i = 0; i < str.length; i++){
    if(!(i % (every + 1))){
      str = str.substring(0, i) + item + str.substring(i);
    }
   }
  return str.substring(1);
}

Result:

> addItemEvery("The quick brown fox jumps over the lazy dogs.", '$', 5)
> "The q$uick $brown$ fox $jumps$ over$ the $lazy $dogs."
Koray Gocmen
  • 674
  • 6
  • 18
1

Here's one of the previous answers, but I wrapped it in a function, and I gave it an "offset" parameter instead of hard coding it.

// https://stackoverflow.com/a/2712896/3480193
addCharToStringEveryXSpots(str, char, offset) {
    if ( ! char ) {
        return str;
    }
    
    let regExPattern = new RegExp('(.{' + offset + '})', 'g');
    
    return str.replace(regExPattern, '$1' + char);
};
Dharman
  • 30,962
  • 25
  • 85
  • 135
RedDragonWebDesign
  • 1,797
  • 2
  • 18
  • 24
0

I did something similar to separate a friendCode for a mobile app but using Array and reduce.

This will take a string, check every n characters and add delimiter at that location.

/**
 * A function to easily inject characters every 'n' spaces
 * @param {string} friendCode The string we want to inject characters in
 * @param {*} numDigits Determines the 'n' spaces we want to inject at
 * @param {*} delimiter The character(s) we want to inject
 */
function formatFriendCode(friendCode, numDigits, delimiter) {
  return Array.from(friendCode).reduce((accum, cur, idx) => {
    return accum += (idx + 1) % numDigits === 0 ? cur + delimiter : cur;
  }, '')
}

formatFriendCode("000011112222", 4, ' ')
// output "0000 1111 2222 "

formatFriendCode("The quick brown fox jumps over the lazy dogs.", 5, '$')
// output "The q$uick $brown$ fox $jumps$ over$ the $lazy $dogs.$"
afreeland
  • 3,889
  • 3
  • 31
  • 42
0
    //first parameter: the string to be divided
    //second parameter: the character used to separate
    //third parameter: the number of characters in each division

    function separateStr(str, divider,  n)
    {
          var ret=[];

          for(let i=0; i<str.length; i=i+n) 
          {
                ret.push(str.substr(i, n))
          };

          return ret.join(divider);
    };

    separateStr('123456789', '.',  3);

    //Output: '123.456.789'