当值包含特定字符串时,使用jq删除键值对

时间:2018-06-23 04:03:16

标签: json shell command-line-interface key-value jq

使用jq如果value包含字符串“ null”,则需要删除特定的key:value对。该字符串可以是“ null”或“ null”。因此需要使用包含而不是完全匹配的字符串。如果不是字符串,它将是一个数字

我的示例json如下:(仅在'th'和'sf'键中应为空值)

'dets':{
   'S1':{
        'type':'class',
        'input': [12,7,6,19],
        'config':{
                'file':'sfile1',
                 'th': -10,
                 'sf': 'null'
                }
         },
    'S2':{
        'type':'class',
        'input': [12,7,6,19],
        'config':{
                'file':'sfile2',
                 'th': -5,
                 'sf': 3
                }
         },
    'S3':{
        'type':'bottom',
        'input': [12,7,16],
        'config':{
                'file':'sfile3',
                 'th': ' null',
                 'sf': 'null '
                }
         }
    }

所需的输出应类似于:

    'dets':{
   'S1':{
        'type':'class',
        'input': [12,7,6,19],
        'config':{
                'file':'sfile1',
                 'th': -10
                }
         },
    'S2':{
        'type':'class',
        'input': [12,7,6,19],
        'config':{
                'file':'sfile2',
                 'th': -5,
                 'sf': 3
                }
         },
    'S3':{
        'type':'bottom',
        'input': [12,7,16],
        'config':{
                'file':'sfile3'
                }
         }
    }

我相信在del(。[] []。config.smoothing_span | select(contains(“ null”)))的线路上有些东西,但是由于类型不同,我遇到了问题。

1 个答案:

答案 0 :(得分:1)

  1. 给定的数据不是有效的JSON,但是它是有效的HJSON,因此以下面向jq的解决方案的第一步是使用hjson将数据转换为JSON:

    hjson -j input.hjson

  2. 应将什么值视为“ null”的概念可能会随时间而改变,因此在下面,让我们定义一个过滤器,该过滤器可用于捕获任何合适的定义,例如 def isnull: . == null or (type=="string" and test("null"));

(也许更好的定义是使用test("^ *null *$")。)

  1. 如果要删除所有值为isnull的键,可以使用walk/1

walk(if type=="object" then with_entries(select(.value|isnull|not)) else . end)

(如果您的jq没有步行,则可以简单地从https://github.com/stedolan/jq/blob/master/src/builtin.jq或网络上的其他位置复制并粘贴其定义。)

假设您的jq有walk,我们可以这样写:

hjson -j input.hjson |
  jq 'def isnull: . == null or (type=="string" and test("null")); 
      walk(if type=="object" 
           then with_entries(select(.value|isnull|not))
           else . end)'
  1. 如果您想“遍历”输入但只注意特定的键,则可以轻松地在(3)中修改选择标准。

delkey

如果您希望更改的范围尽可能缩小,则可以使用map_values,例如结合用于检查并可能删除特定键的辅助功能:

  # key is assumed to be a filter, e.g. .foo
  def delkey(key): if key | isnull then del(key) else . end;
  .dets |= map_values(.config |= (delkey(.th) | delkey(.sf)))

delkeys

如果要检查几个特定的​​键,则定义一个用于检查键列表的功能可能会更方便:

# keys is assumed to be an array of strings
def delkeys(keys):
  with_entries(select(.key as $k
    | (keys|index($k)) and (.value|isnull) | not));

.dets |= map_values(.config |= delkeys(["th", "sf"]))