skip to Main Content

I have a fairly long hex string Buffer.toString("hex") that I want to print to a log file in a block of 32 tuplets each.

So basically going from
e01102020809020300800202020809020208095f520c8066054445472b44739621e0d003040401d21044454946583532463447444a4d010000d3104445472b445333374f53474b32010000d4104445472b44533337474b563033010000d503040401d6104445472b444342324354473031010000d7104445472b44504450535f5f5f5f0106009000

to

e0 11 02 02 08 09 02 03 00 80 02 02 02 08 09 02 02 08 09 5f 52 0c 80 66 05 44 45 47 2b 44 73 96
21 e0 d0 03 04 04 01 d2 10 44 45 49 46 58 35 32 46 34 47 44 4a 4d 01 00 00 d3 10 44 45 47 2b 44
53 33 37 4f 53 47 4b 32 01 00 00 d4 10 44 45 47 2b 44 53 33 37 47 4b 56 30 33 01 00 00 d5 03 04
04 01 d6 10 44 45 47 2b 44 43 42 32 43 54 47 30 31 01 00 00 d7 10 44 45 47 2b 44 50 44 50 53 5f
5f 5f 5f 01 06 00 90 00

I have tried hex.replace(/.{64}/g, "$1n") to wrap the hex string after 32 tuplets but don’t know how to add the spaces between the tuplets now.
I would prefer to do that in one regex, if possible?

4

Answers


  1. You can’t really do this in one regex in JavaScript because it doesn’t support features like variable length lookbehind (in general), conditional replacement or the G meta sequence. You can just split the string into chunks of up to 64 characters and then those strings into chunks of up to 2 characters, joining the splits with space and newline:

    const hex = 'e01102020809020300800202020809020208095f520c8066054445472b44739621e0d003040401d21044454946583532463447444a4d010000d3104445472b445333374f53474b32010000d4104445472b44533337474b563033010000d503040401d6104445472b444342324354473031010000d7104445472b44504450535f5f5f5f0106009000'
    
    const out = hex
        .match(/(.{1,64})/g)
        .map(s => s.match(/.{1,2}/g).join(' '))
        .join('n')
    
    console.log(out)

    Note I’ve used {1,2} in the second regex in case your data might have an odd number of characters. If it won’t, you can simply use {2}.

    Login or Signup to reply.
  2. To format your hex string into blocks of 32 tuplets each with spaces and line breaks in JavaScript, you can use a two-step approach:

    1. Add spaces between each pair of characters.
    2. Insert a newline after every 32 pairs (96 characters, including spaces).
    let hexString = "e01102020809020300800202020809020208095f520c8066054445472b44739621e0d003040401d21044454946583532463447444a4d010000d3104445472b445333374f53474b32010000d4104445472b44533337474b563033010000d503040401d6104445472b444342324354473031010000d7104445472b44504450535f5f5f5f0106009000";
        
    hexString = hexString.replace(/(..)/g, "$1 ").trim(); 
        
    hexString = hexString.replace(/(.{96})/g, "$1n").trim(); 
        
     console.log(hexString);

    This will give you a formatted string as desired.

    Login or Signup to reply.
  3. You could also do your looping inside the regex engine:

    const src = 'e01102020809020300800202020809020208095f520c8066054445472b44739621e0d003040401d21044454946583532463447444a4d010000d3104445472b445333374f53474b32010000d4104445472b44533337474b563033010000d503040401d6104445472b444342324354473031010000d7104445472b44504450535f5f5f5f0106009000';
    
    function format(src) {
      let bytes = 0;
      return src.replace(/../g, byte => {
        if (bytes === 31) {
          bytes = 0;
          return `${byte}n`;
        }
        bytes++;
        return `${byte} `;
      });
    }
    
    console.log(format(src));

    (That could probably be code-golfed down a little, but I wanted to be clear.)

    That uses the feature of the string .replace() method, which allows a function to be passed as the second argument. The format() function keeps a counter and resets it on newlines.

    The regular expression matching will be done over and over, but that regex will simply "eat" two characters on each iteration and then invoke the callback each time. It’s not re-scanning the entire source string. The return string is built inside the regex engine from the values returned by the callback.

    Login or Signup to reply.
  4. You can use B to assert a non-word boundary after a tuplet to insert spaces only between tuplets:

    const hex = 'e01102020809020300800202020809020208095f520c8066054445472b44739621e0d003040401d21044454946583532463447444a4d010000d3104445472b445333374f53474b32010000d4104445472b44533337474b563033010000d503040401d6104445472b444342324354473031010000d7104445472b44504450535f5f5f5f0106009000';
    console.log(hex.replace(/.{64}/g, '$&n').replace(/..B/g, '$& '))
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search