JQ:枚举对象流

时间:2015-06-01 22:17:24

标签: object stream enumerate jq

我有一个充满对象的管道,我正在尝试使用jq为流中的每个对象添加一个累积计数字符串,以获得以下输出

{"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"}

如下所示,但我确信我不需要依赖awk。

yes '{}' | head -n10 | jq -c '.count|="Num_ "' | awk '{printf("%s%03i%s\n",$1,NR-1,$2)}'

到目前为止,我已经找到了一种方法来计算我的物品,但是因为我沾满了所有的物体,所以感觉非常浪费。

yes '{}' | head -n10 | jq -c -s 'range(0;.|length) as $i|(.[$i]|.count|=$i)'

我会继续玩这个,但我认为这是我学习的机会。我有什么想法可以更有效地做到这一点?

我还想出了一种黑客方式来格式化字符串,因为我假设<我的流中有1000个对象。

yes '{}' | head -n20 | jq -c -s 'range(0;.|length) as $i|(.[$i]|.count|=(1000+$i|tostring|ltrimstr("1")|"Num_"+.))'

2 个答案:

答案 0 :(得分:1)

使用-s(slurp)选项,您可以执行以下操作:

yes '{}' | head -n10 | jq -s 'to_entries | map(.value.count = .key)[].value'

但是,是的,就像你自己说的那样,啜饮是浪费;而且,更糟糕的是,它阻止了流。

你可以做的是,对于每个元素,压缩它以便它需要一条线(通过jq -c '.'管道;你的"是"对象样本不需要它,但来自管道的任意对象可能)然后在你的shell上迭代它。在鱼壳上,但容易携带到其他任何东西:

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

答案 1 :(得分:1)

使用最新版本的jq(即使用foreach和输入),例如jq 1.5rc1,可以在以下几行中高效且优雅地执行任务:

yes 1 | head -n10 |\
 jq -c -n 'foreach inputs as $line (0; .+1; {"count": "Num_\(.)"})'

这里的关键是使用-n选项。