Можно ли использовать уникальный оператор над потоком в JQ - PullRequest
1 голос
/ 04 июня 2019

следующий код

for i in {1..10}; do 
    echo '{"key":'$(($RANDOM % 3))'}'
    sleep 1 
done | jq -n '[inputs]|unique'

напечатает (если бы они все появились):

[
  {
    "key": 0
  },
  {
    "key": 1
  },
  {
    "key": 2
  }
]

Проблема в том, что вам нужно подождать 10 секунд, чтобы увидеть результат (10 * sleep 1). Есть ли потоковая версия, когда новый элемент появляется, он сбрасывает его в стандартный вывод?

1 Ответ

1 голос
/ 04 июня 2019

Вот ориентированное на поток определение "уникального":

def unique(stream):
  foreach stream as $s ({};
     ($s|type) as $t
     | ($s|tostring) as $y
     | if .[$t][$y] then .emit = false
       else .emit = true | (.item = $s) | (.[$t][$y] = true)
       end;
     if .emit then .item else empty end );

Вы можете использовать его с параметром командной строки -n следующим образом:

unique(inputs)

Замечания по программированию

Вышеупомянутая ориентированная на поток версия «unique» не влечет за собой сортировку и в этом смысле более эффективна по времени, чем встроенная версия.

Требуемое пространство является линейным по количеству различных предметов. Если известно, что элементы в потоке отсортированы (или расположены так, чтобы все равные элементы были смежными), тогда может представлять интерес uniq, как определено ниже.

уник / 1

Поваренная книга jq дает это определение для uniq, которое больше похоже на Linux uniq:

def uniq(s):
  foreach s as $x (null;
    if . == null or .emitted != $x then {emit: true, emitted: $x}
    else .emit = false
    end;
    if .emit then $x else empty end);
...