【问题标题】:How I can round digit on the last column to 2 decimal after a dot using JQ?如何使用 JQ 将最后一列的数字舍入到小数点后 2 位?
【发布时间】:2018-02-17 09:55:58
【问题描述】:

如何将最后一列的数字四舍五入到小数点后两位?

我有 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.08691986891395370.20963260148716 但我想要 210.09370.21

【问题讨论】:

    标签: arrays json csv unix jq


    【解决方案1】:

    这是您当前的过滤器,稍作重新格式化:

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

    【讨论】:

      【解决方案2】:

      根据您的 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;
      

      【讨论】:

      • 感谢您的回答。但是我检查了这个,我看到一个错误: jq: error: round/0 is not defined at , line 1: def roundit: .*100.0 |round/100.0; ["名称","描述","结果"], (.hits.hits[]._source | [.acb.item.name, .acb.item.description, .value|roundit])| @csv jq:1 编译错误是的,我使用的是 linux(jq 版本 1.5)
      • 是的,您似乎也无法使用round。但是我们也可以用floor 来实现。不完全相同,但足够接近。
      【解决方案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
      

      【讨论】:

        猜你喜欢
        • 2018-01-17
        • 1970-01-01
        • 2014-06-28
        • 1970-01-01
        • 2020-06-12
        • 1970-01-01
        • 1970-01-01
        • 2012-01-03
        • 1970-01-01
        相关资源
        最近更新 更多