I've got a pipe full of objects and I am trying to add a accumulating count string to each object in a stream with jq
to get the following output
{"count":"Num_000"}
{"count":"Num_001"}
{"count":"Num_002"}
{"count":"Num_003"}
{"count":"Num_004"}
{"count":"Num_005"}
{"count":"Num_006"}
{"count":"Num_007"}
{"count":"Num_008"}
{"count":"Num_009"}
Something like the following but I'm sure I don't need to rely on awk.
yes '{}' | head -n10 | jq -c '.count|="Num_ "' | awk '{printf("%s%03i%s\n",$1,NR-1,$2)}'
So far I have found one way to get the count into my objects but it feels very wasteful since I slurp up all the objects.
yes '{}' | head -n10 | jq -c -s 'range(0;.|length) as $i|(.[$i]|.count|=$i)'
I'm going to keep playing with this but I figured this was a chance for me to learn. Any ideas how i can do this more efficiently?
I've also figured out one hack-y way to format the string since I assume < 1000 objects in my stream.
yes '{}' | head -n20 | jq -c -s 'range(0;.|length) as $i|(.[$i]|.count|=(1000+$i|tostring|ltrimstr("1")|"Num_"+.))'
Using the -s
(slurp) option, you could do the following:
yes '{}' | head -n10 | jq -s 'to_entries | map(.value.count = .key)[].value'
But, yes, as you said yourself, slurping is wasteful; and, even worse, it blocks the stream.
What you could do instead is, for each element, compact it so that it takes one line (piping it through jq -c '.'
; your "yes" object sample doesn't need it, but arbitrary objects coming from the pipeline might) and then iterate through it on your shell. On fish shell, but easily portable to anything else:
set j 0
for i in (yes '{}' | head -n 100000 | jq -c '.')
set j (expr $j + 1)
echo $i | jq --arg j $j '.count = ($j | tonumber)'
end