从awk返回中提取数值

时间:2019-12-10 09:45:23

标签: bash shell jq

对于监督系统,我需要通过nrpe将2个有关延迟的值返回到我的监督服务器。

这是我正在处理的值(我将其放在文件中:test.txt):

{"status":"success","data":{"resultType":"vector","result":[{"metric":{"project_site":"AUB"},"value":[1575277537.052,"0.3889104875437488"]},{"metric":{"project_site":"VDR"},"value":[1575277537.052,"0.2267407994117705"]}]}}

我需要提取0.38891048754374880.2267407994117705

我正在使用它:

for i in $(""cat test.txt | awk -F ',' '{print $5 $NF}' | grep -o '[0.0001-9999.9]\+'""); do echo $i; done

我不确定这是最好的方法,尤其是因为我必须在每行之前为行1添加“ AUB”,为行2添加“ VDR”。喜欢:

AUB : 0.3889104875437488 seconds
VDR : 0.2267407994117705 seconds

2 个答案:

答案 0 :(得分:2)

使用解析JSON,例如:

$ jq -r '.data.result[] | "\(.metric.project_site) : \(.value[1]) seconds"' file
AUB : 0.3889104875437488 seconds
VDR : 0.2267407994117705 seconds

答案 1 :(得分:0)

我已通过@oguzismail给出了答案,如果可能的话,我会重复他们的建议,改用jq

如果您输入的内容不是有效的JSON,则您的方法有几处错误,其中有几处与效率和常规做法有关,而不仅仅是完全错误。

  1. 您的正则表达式有误。参见下文。
  2. 避免使用useless cat.
  3. 如果您仍在使用Awk,则不需要grep。参见useless use of grep.
  4. Quote your variable.
  5. 仅在这种情况下,您要完全删除无用的echo。捕获标准输出,以便可以将其echo转换为标准输出,这只是在浪费过程(除非您特别想打断引号,作为上一项的特殊情况;但是这里不是这种情况)。
  6. 不清楚您希望空字符串""完成什么。在用引号删除完成shell之后,""cat就是cat

更详细地讲,[0.0001-9999.9]与单个字符匹配,即0.0(哦,我们已经提到过了,不是吗?)或0(同上)或在199之间(等等)。简而言之,grep根本不是用于搜索数字范围的工具。幸运的是,Awk也可以轻松做到这一点。

那么,这就是尝试重构以消除这些问题。

awk -F ',' '{ split("5:" NF, a, ":"); split("AUB:VDR", l, ":")
  for (i=1; i<=2; i++) {
    n = $a[i]; gsub(/[]}"]+/, "", n);
    if (n >= 0.0001 && n <= 9999.9)
      print l[i] ": " n " seconds"} }' test.txt

这非常脆弱,因为它会硬编码(不是?)JSON数据的表面结构中字符串的位置,而这些位置可能会更改而不会发出警告。

split是一种将数字5和NF放入数组a的工具。我们为相应的标签创建具有相同长度的第二个数组。然后,我们遍历第一个数组,并使用数字作为当前记录字段的索引。我们删去所有引号和方括号,然后对由此提取的字段执行数字比较。最后,我们在打印文本的前面添加另一个数组中的相应标签。