jq has built-in ability to convert numbers to string or concatenate strings.
How can I format strings inside jq similar to printf like padding (%4s).

For example, how can I force number to occupy 10 char spaces with left alignment?
echo '{"title" : "A sample name", "number" : 1214}' | jq '(.title) + " " + (.number | tostring)'

3 Answers 3


jq can reference expressions inside string using \(foo)

String interpolation - \(foo)

Inside a string, you can put an expression inside parens after a backslash. Whatever the expression returns will be interpolated into the string.

jq '"The input was \(.), which is one less than \(.+1)"' <<<  42


"The input was 42, which is one less than 43"
  • This is great. Any jq syntax is valid between the parentheses. For example, array iteration, field access. So echo '["a", "b", "c"]' | jq -r '"Testing \(.[])"' yields 3 lines of output Testing a, Testing b, and Testing c Oct 26 at 4:37
  • @JimmieTyrrell that's cool, thanks. I can't even process that mentally.
    – dosmanak
    Nov 15 at 15:36

One way of doing it would be to not trying to do it in jq, and instead use jq to output a shell statement to do it in the shell instead:

eval "$(
    jq -r -n '
        { "title": "A sample name", "number": 1214 } |
        [ "printf", "%s %10s\\n", .title, .number ] | @sh'


eval "$(
    printf '%s\n' '{ "title": "A sample name", "number": 1214 }' |
    jq -r '[ "printf", "%s %10d\\n", .title, .number ] | @sh'


printf '%s\n' '{ "title": "A sample name", "number": 1214 }' |
    eval "$(
        jq -r '[ "printf", "%s %10s\\n", .title, .number ] | @sh'

The jq command would output

'printf' '%s %10d\n' 'A sample name' 1214

using the @sh operator to properly quote each bit of the command safely. When evaluated, this would output

A sample name       1214

A similar approach, but giving you two variable assignments instead:

jq -r -n '
    { "title": "A sample name", "number": 1214 } |
    @sh "title=\(.title)",
    @sh "number=\(.number)"'

You would then use these variables in your script:

unset -v title number

eval "$(
    jq -r -n '
        { "title": "A sample name", "number": 1214 } |
        @sh "title=\(.title)",
        @sh "number=\(.number)"'

printf '%s %10s\n' "$title" "$number"

For cases where the data is known to be nice (the title can't contain newlines, for example), you could possibly do

jq -r -n '
    { "title": "A sample name", "number": 1214 } |
    [ .title, .number ] | @sh' |
xargs printf '%s %10s\n'

That is, make sure that the data is quoted, and then pass it to printf in the shell (this would call the external utility printf, not a shell built-in).

  • 3
    Beware jq outputs numbers in English format (with . as the decimal radix character for instance), while printf (for those implementations that accept floats for %d) expects it in the locale format. Several printf implementations like that of zsh or ksh88/ksh93 (those found as sh on some systems) will interpret arguments for %d as arithmetic expressions and as such can execute arbitrary commands, so it would be important to sanitise the input if those .number can't be guaranteed to be numbers. Using %10s instead of %10d would avoid the problem. Aug 27, 2021 at 18:02

jq does not have printf. One way could be; Partially taken from here:

echo '{"title" : "A sample name", "number" : 1214}' | 
jq '(.title) + " " + 
    (.number | tostring | (" " * (10 - length)) + .)'

Perhaps better added as a module.

Personally I quickly find jq lines to be somewhat messy and resort to perl, python, php or similar if doing anything beyond the basics. (But that is me :P)

E.g with php:

#! /usr/bin/env php

$data = json_decode(file_get_contents("php://stdin"));

printf("%s: %10d\n", $data->title, $data->number);


(Would add error-checking etc as well of course.)


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .