Как использовать jq для вывода десятичного минимума в Linux

Учитывая следующую команду jq и Json: (Только команда jq)

echo '{"foo": {"bar": 0.00000072}}' | jq 'map_values( . + {"bar": .bar|tostring} )'
{
  "foo": {
    "bar": "7.2e-07"
  }
}

Я пытаюсь отформатировать вывод как:

{
  "foo": {
    "bar": "0.00000072"
  }
}

OR

{
  "foo": {
    "bar": 0.00000072
  }
}

person Victor Marrerp    schedule 24.12.2018    source источник
comment
На мой взгляд, это не дубликат связанного вопроса stackoverflow.com/questions/42956806/, потому что здесь числовая строка JSON считается приемлемой, тогда как другой вопрос намного сложнее (т. е. практически невозможно) решить, используя только jq.   -  person peak    schedule 24.12.2018
comment
Хм. Я мог увидеть уродливый взлом, используя только jq, чтобы построить ответ для другого поверх того, что у вас здесь (используя tojson и уникальный сигил в качестве токена поиска / замены строки для генерации необработанного вывод, который оказывается действительным JSON), но он действительно более сложен.   -  person Charles Duffy    schedule 24.12.2018
comment
Не уверен, что вы имеете в виду ... вам придется написать новый симпатичный принтер, а это довольно большая работа. Потребность в пользовательском контроле над форматированием настолько велика, что я надеюсь, что это произойдет раньше, а не намного позже, поэтому пока я склонен подождать ...   -  person peak    schedule 24.12.2018
comment
Спасибо всем за ответы. поскольку совершенно очевидно, что только с jq это невозможно сделать, я понимаю, что в этом вопросе stackoverflow.com/questions/42956806/ - это самый чистый вариант, который адаптируется к моим потребностям.   -  person Victor Marrerp    schedule 25.12.2018


Ответы (1)


Вы можете использовать эту универсальную функцию:

def to_decimal:
  def rpad(n): if (n > length) then . + ((n - length) * "0") else . end;
  def lpad(n): if (n > length) then ((n - length) * "0") + . else . end;
  tostring
  | . as $s
  | capture( "(?<sgn>[+-]?)(?<left>[0-9]*)(?<p>\\.?)(?<right>[0-9]*)(?<e>[Ee]?)(?<exp>[+-]?[0-9]+)" )
  | if .e == "" then $s
    else (.left|length) as $len
    | (.exp | tonumber) as $exp
    | if $exp < 0 then .sgn + "0." + (.left | lpad(1 - $exp - $len)) + .right
      else .sgn + (.left | rpad($exp - $len)) + "." + .right
      end
    end ;

Пример:

"7.2e-07"|to_decimal

дает:

"0.00000072"
person peak    schedule 24.12.2018
comment
Это был бы действительно отличный ответ на уже существующий / канонический экземпляр этого вопроса (stackoverflow.com/questions/42956806/, теперь связанный с пометкой текущего экземпляра как дублирующий). - person Charles Duffy; 24.12.2018
comment
@CharlesDuffy - Вау! Я не осознавал, что у меня есть магические способности (открывать заново). - person peak; 24.12.2018
comment
Я надеюсь, что ты уже будешь золотым значком в jq; Я выучил большую часть того, что знаю о языке, из ваших ответов. - person Charles Duffy; 24.12.2018
comment
@CharlesDuffy - я могу потерять это, болтая здесь, но позвольте мне сказать, что исходящий от вас, это настоящий комплимент! Считаю это платиновым значком :-) - person peak; 24.12.2018