Bash脚本/ JSON-从{“ Key”:“ Duration”,“ Value”:“ N”}中提取数字值

时间:2019-11-22 11:34:07

标签: json linux bash grep jq

环境-Ubuntu Server 18.04 LTS / Bash

我需要从以下键/值对{"Key":"Duration","Value":"40453"}中为以下定义的每个JSON格式记录提取持续时间。

我只想提取持续时间的数值。

在此先感谢您提供所有建议。

{"fields":[
    {"Key":"StartDateTime","Value":"06\/11\/2019 17:58:36"},
    {"Key":"EndDateTime","Value":"06\/11\/2019 17:59:17"},
    {"Key":"Duration","Value":"40453"},   
    {"Key":"Extension","Value":"1544027"},
    {"Key":"OtherParty","Value":"345345"},
    {"Key":"Direction","Value":"Outgoing"},
    {"Key":"AgentGroup","Value":"ABCDEF"},
    {"Key":"ChannelName","Value":"Foo"},
    {"Key":"CallerNumber","Value":"1544027"},
    {"Key":"CallerName","Value":"Bar"},
    {"Key":"CalledNumber","Value":"123123"},  
    {"Key":"Called_Name","Value":""},
    {"Key":"AnnotationText","Value":""},
    {"Key":"SipToAddress","Value":""},
    {"Key":"SipFromAddress","Value":""},
    {"Key":"ExtensionName","Value":"Foo"},
    {"Key":"SuppressedCall","Value":"False"},
    {"Key":"ScreenRecording_ID","Value":""},
    {"Key":"ScreenRecording_Extra","Value":""},
    {"Key":"OrganisationID","Value":"65"},
    {"Key":"RedirectingNumber","Value":""},
    {"Key":"RedirectingName","Value":""},
    {"Key":"RedirectionNumber","Value":""},
    {"Key":"RedirectionName","Value":""},
    {"Key":"RBRCallGUID","Value":"0000238E00D345E6201123123583661"},
    {"Key":"AnnotationTextFirst","Value":""},
    {"Key":"1001","Value":""},
    {"Key":"1002","Value":""}
]}

4 个答案:

答案 0 :(得分:1)

JSON查询工具或诸如jq之类的“过滤器”最适合查询JSON。

但是由于您的问题也被标记为#grep,因此以下内容应该使用egrep(带有选项-E的GNU或BSD grep)来完成工作:

egrep -o '"Key".*:.*"Duration".*,.*"Value".*:.*"[^"\n]*"' data.json | egrep -o '[0-9]+'

这假设"Key""Value"在文件data.json中位于同一行。请注意,当这些grep查询分布在两行或更多行时,此grep查询将不起作用!

还有其他一些支持多行模式匹配的grep工具,例如ripgrepugrep。这些在搜索JSON文件和源代码时更强大。 Ugrep还支持带有选项-P的向后引用(Perl匹配),我们可以简单地在%1中向后引用--format输出值(用于自定义格式的输出) :

ugrep -P '"Key".*:.*"Duration".*,[^"]*"Value".*:.*"([^"\n]*)"' --format='%1%~' data.json

答案 1 :(得分:0)

由于没有规定要使用哪个实用程序来实现您的要求,因此我将独立发布答案。

您不清楚“ ...仅是数值”是什么意思,因为JSON中的所有值都是字符串文字。如果您想删除引号,则可以使用jtc实用程序来完成:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

此外,如果您需要在JSON中查找多个(所有)此类值(必须存在多个),请在bash $ <file.json jtc -w'<Duration>[-1][Value]' -qq 40453 bash $ 词素后添加一个冒号(:)量词:Duration

如果要确定Duration的值实际上是一个表示为字符串的数值,则使用以下形式:

<Duration>:[-1][Value]

-让我知道这是否不是您的意思,然后我将更新我的答案。

PS。我是bash $ <file.json jtc -w'<Duration>:[-1][Value]:<^\d+$>R' -qq 40453 bash $ 工具的创建者-JSON cli处理器实用程序。 PSS。 SO要求披露与产品的隶属关系。

答案 2 :(得分:0)

使用jq,将所有持续时间值捕获为数字的解决方案是:

.fields[] 
| select(.Key == "Duration")
| .Value
| tonumber

如果您只对第一个时长感兴趣,或者如果您最多知道一个这样的时长,则将以上内容包装在对first/1的调用中,即使用格式first(...)

答案 3 :(得分:-3)

非常感谢您抽出宝贵的时间分享您的知识和专业知识。

最后,对于这个挑战,我能够如下提取持续时间值:

extract_durations() {
    ( cat metadata_compressed.json | jq '.' | grep Duration -A 1 | grep "Value" | sed 's/ [^0-9]*//g' | tr -d '"' ) > raw_dur.txt
}

返回的数据示例:

50531
51718
254000
53609
152719
58797

这很明显,但是有效。

添加更好的(更少粗略的)答案:

cat metadata.json | jq -r'.fields [2]。值'