Sprintf: merge text and variables in Javascript

The function sprintf is common in many programming languages, as a way to merge programme variables in a text string. It has good options for formatting, such as outlining text string, or setting the precision of numbers. In many cases, you don’t need those, and a simple function that just inserts the variables at the right place is fine, and a better option in order to keep your JavaScript code short. See the example below:

// Simple string concatenation
var html1 = '<a href="' + url + '">' + link + '</a>';

// Using sprintf
var html2 = sprintf( '<a href="%s">%s</a>', url, link );

In this article, I share a simple function doing string replacements. For sprintf alternatives with the full functionality, just Google on ‘javascript sprintf’, and you will find some good versions. If you don’t need all that, read on.

The function presented below is doing just the simple string replacement.

function sprintf( format )
{
  for( var i=1; i < arguments.length; i++ ) {
    format = format.replace( /%s/, arguments[i] );
  }
  return format;
}

This function uses two features of JavaScript that I will highlight here:

Variable number of arguments

Despite the definition ‘function sprintf( format )‘, you can add any number of arguments. They can not be called by name, but only by reading the array arguments.

Regular expression replacements

The replace method can be used with strings and regular expressions as the first parameter. If we would have used it with a string ‘”%s”‘, it would have replaced all occurrences of ‘%s’ with the first argument after format. Using the regular expression ‘/%s/’, it will only replace the first occurrence. (If the global option was given , as in ‘/%s/g’, it would have replaced all occurrences ). Each subsequent occurrence of ‘%s’ will be replaced in the next loop, using the next argument.

Notes

Note that in this simple function, there is no way to escape the ‘%s’ string, i.e. if the results string can not contain a ‘%s’ string, it will always be replaced by an argument (provided there are sufficient arguments).

Note also that the number of occurrences of ‘%s’ in the format should match the number of arguments. However, it will not produce any errors. If there are less occurrences of ‘%s’, the excess arguments are simply ignored, if there are not enough arguments, the remaining occurrences of ‘%s’ will still be in the returned string.

This post is also available in: Dutch

4 thoughts on “Sprintf: merge text and variables in Javascript

  1. Andy

    Hi, nice explanation of why to use “replace”.

    However, we need to start the loop with i=0 and add the arguments variable to the input parameters of the function.

    Also, you can cater for the %d substitution (for numbers) as well as strings quite easily with a pattern of: %[sd]

    Reply
    1. Harry Post author

      Hi Andy,
      Thanks for the feedback.
      You can refer to a function’s arguments within the function by using the arguments object. This object contains an entry for each argument passed to the function, the first entry’s index starting at 0.
      So arguments[0] is the format, and arguments[1], etc are the replacement values. By using the arguments object, we can use a variable number of arguments.
      The alternative would be to specify an array of reaplcement values as second argument, in which case we would indeed have to start counting at 0, as in:

      function sprintf( format, args )
      {
        for( var i=0; i < args.length; i++ ) {
          format = format.replace( /%s/, args[i] );
        }
        return format;
      }
      
      // Now use array as second argument
      var html3 = sprintf( '%s', [url, link] );
      
      Reply
  2. John Pallister

    Hi Harry, I found your page via Google and it was very useful, thanks! I wanted to do something similar and this is what I ended up with:


    function log(msg, ...args) {
    // Primitive "sprintf()" for Skewer log().
    var i=0;

    msg=msg.replace(/%[%dfos]/g, function (m) { return m=="%%" ? "%" : args[i++].toString(); });
    skewer.log(msg);
    }

    Reply
  3. Jakub

    More javascript magic. Equvalent of the sprintf(format) function above.

    function sprintf() {
    return [].reduce.call(arguments, function (txt, arg) { return txt.replace(/%s/, arg) || txt });
    }

    Reply

Leave a Reply

Your email address will not be published.