如何使用JQ将最后一列的数字舍入到点后的2位小数?

时间:2017-09-08 12:53:43

标签: arrays json csv unix jq

我如何将最后一列的数字舍入到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

3 个答案:

答案 0 :(得分:1)

我会通过管道传递给 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 :(得分:1)

根据您的jq版本,您可以访问某些cstdlib math functions(例如sincos)。因为你在* 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;

答案 2 :(得分:0)

以下是您当前使用次要重新格式化的过滤器:

  ["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