Как округлить цифру по последнему столбцу до 2 десятичных знаков?

У меня есть JSON:

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 9,
    "successful": 9,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 2.575364,
    "hits": [
      {
        "_index": "my-2017-08",
        "_type": "log",
        "_id": "AV5V8l0oDDWj-VP3YnCw",
        "_score": 2.575364,
        "_source": {
          "acb": {
            "version": 1,
            "id": "7",
            "owner": "pc",
            "item": {
              "name": "Account Average Latency",
              "short_name": "Generate",
              "description": "Generate of last month"
            },
            "service": "gsm"
          },
          "@timestamp": "2017-07-31T22:00:00.000Z",
          "value": 210.08691986891395
        }
      },
      {
        "_index": "my-2017-08",
        "_type": "log",
        "_id": "AV5V8lbE28ShqBNuBl60",
        "_score": 2.575364,
        "_source": {
          "acb": {
            "version": 1,
            "id": "5",
            "owner": "pc",
            "item": {
              "name": "Profile Average Latency",
              "short_name": "Profile",
              "description": "Profile average latency of last month"
            },
            "service": "gsm"
          },
          "@timestamp": "2017-07-31T22:00:00.000Z",
          "value": 370.20963260148716
        }
      }
    ]
  }
}

Я использую JQ для получения данных CSV:

["Name","Description","Result"],(.hits.hits[]._source | [.acb.item.name,.acb.item.description,.value])|@csv

Я вижу результат:

"Name","Description","Result"
"Account Average Latency","Generate of last month",210.08691986891395
"Profile Average Latency","Profile average latency of last month",370.20963260148716

У меня есть 210.08691986891395 и 370.20963260148716 , но я хочу 210.09 и 370.21 .

5
Serg R 8 Сен 2017 в 15:53

3 ответа

Лучший ответ

Я бы передал его awk по конвейеру:

jq -r '["Name","Description","Result"],(.hits.hits[]._source |
       [.acb.item.name,.acb.item.description,.value])|@csv' yourfile | 
       awk 'BEGIN{ FS=OFS="," }NR>1{ $3=sprintf("%.2f",$3) }1'

Выход:

"Name","Description","Result"
"Account Average Latency","Generate of last month",210.09
"Profile Average Latency","Profile average latency of last month",370.21
1
RomanPerekhrest 8 Сен 2017 в 14:29

В зависимости от вашей сборки jq у вас может быть доступ к некоторым математическим функциям cstdlib (например, , sin или cos). Поскольку вы пользуетесь * nix, скорее всего, так и есть. В моей конкретной сборке у меня нет доступа к round но, возможно, вы делаете.

def roundit: .*100.0|round/100.0;
["Name","Description","Result"],
(.hits.hits[]._source | [.acb.item.name, .acb.item.description, (.value|roundit)])
    | @csv

К счастью, это может быть реализовано в терминах floor, к которым у меня есть доступ.

def roundit: .*100.0 + 0.5|floor/100.0;
6
Jeff Mercado 8 Сен 2017 в 16:33

Вот ваш текущий фильтр с небольшим переформатированием:

  ["Name", "Description", "Result"]
, (   .hits.hits[]._source
    | [.acb.item.name, .acb.item.description, .value]
  )
| @csv

Вот фильтр, который округляет столбец значений. Обратите внимание, что мы делаем это после @csv, чтобы у нас был полный контроль над строкой

def round:                                                # e.g.
    (split(".") + ["0"])[:2]                              # ["210","08691986891395"]
  | "\(.[1])000"[:3] as $x | [.[0], $x[:2], $x[2:3]]      # ["210","08","6"]
  | map(tonumber)                                         # [210,8,6]
  | if .[2] >  4 then .[2] = 0 | .[1] += 1 else . end     # [210,9,0]
  | if .[1] > 99 then .[1] = 0 | .[0] += 1 else . end     # [210,9,0]
  | ["\(.[0])", "00\(.[1])"[-2:]]                         # ["210","09"]
  | join(".")                                             # 210.09
;

  (   ["Name", "Description", "Result"] | @csv )
, (   .hits.hits[]._source
    | [.acb.item.name, .acb.item.description, .value]
    | @csv
    | split(",") | .[-1] |= round | join(",")
  )

Если этот фильтр находится в filter.jq, а пример данных находится в data.json, тогда команда

$ jq -Mr -f filter.jq data.json

Производит

"Name","Description","Result"
"Account Average Latency","Generate of last month",210.09
"Profile Average Latency","Profile average latency of last month",370.21
0
jq170727 8 Сен 2017 в 17:14