DEV Community

Julien Gonzalez
Julien Gonzalez

Posted on

jq, reduce, inputs & null input

#jq

Say you have a file (e.g. numbers.txt) with one number per line and you need to sum them all up.

1
2
3
Enter fullscreen mode Exit fullscreen mode

First off, for such a simple task and such a small file you can always do:

# jq -s 'add' numbers.txt
6
Enter fullscreen mode Exit fullscreen mode

In case you wonder: -s causes the file to be loaded into an array which is then passed to add. So essentially what's happening is [1,2,3] | add.

However for the purpose of this post, we're going to use reduce & friends:

# jq -n 'reduce inputs as $n (0; . + $n)' numbers.txt
6
Enter fullscreen mode Exit fullscreen mode

The -n option is quite important here and is something that has tripped me up way too many times that I care to admit.

But before I explain what -n means, let's see what running the same command without it yields:

# jq 'reduce inputs as $n (0; . + $n)' numbers.txt
5
Enter fullscreen mode Exit fullscreen mode

Obviously wrong and we can guess that the first input (i.e. the first line of the file) has gone AWOL. (Another thing I wasted way too much time on.)

The clue is in the doc for inputs:

Outputs all remaining inputs, one by one.

So how do I get the first input? With . of course:

# jq 'reduce inputs as $n (.; . + $n)' numbers.txt
6
Enter fullscreen mode Exit fullscreen mode

So . holds the first line of the file whilst inputs holds the remaining ones.

However sometimes the initialisation sequence of a reducer is similar to the iteration sequence e.g.,

# jq 'reduce inputs as $n (. * 10; . + ($n * 10))' numbers.txt
60
Enter fullscreen mode Exit fullscreen mode

Again, this is a simple and contrived example so it's probably ok to repeat yourself here but there's a way to have the entire file emitted by inputs. That's where -n comes in:

Don't read any input at all. Instead, the filter is run once using null as the input.

So -n causes null to be emitted as the first input, which means that 1 and all the remaining numbers are emitted by inputs:

# jq -n 'reduce inputs as $n (0; . + ($n * 10))' numbers.txt
60
Enter fullscreen mode Exit fullscreen mode

The -n is often useful when you just want to try out some stuff quickly e.g.,

# jq -n '[1,2,3] | add'
6
Enter fullscreen mode Exit fullscreen mode

Top comments (0)