需要用新值替换json中的tags字段

时间:2016-11-26 04:16:52

标签: json sed jq

我正在尝试编写一个批处理脚本来更改名为example1.json和example2.json的以下2个jsons的“tags”键的值。

输入example1.json

{
 "info": {
    "title": "My example swagger 2",
    "version": "1.0"
  },
  "paths": {
    "/v1/resource3": {
        "get": {
            "description": "This is the example2",
            "tags": [
                "example2"
            ],
            "consumes": [
                "*/*"
            ]
        }
    },
    "/v1/resource4": {
        "get": {
            "tags": [
                "example2"
            ],
            "consumes": [
                "*/*"
            ]
        }
    }
  }
}

输入example2.json

{
  "info": {
    "title": "My example swagger 1",
    "version": "1.0"
  },
  "paths": {
    "/v1/resource1": {
        "get": {
            "description": "This is the example1",
            "tags": [
                "tag1"
            ],
            "consumes": [
                "*/*"
            ]
        }
    },
    "/v1/resource2": {
        "get": {
            "tags": [
                "tag1"
            ],
            "consumes": [
                "*/*"
            ]
        }
    }
  }
}

预期输出是两个具有相同名称的jsons,但标签值现在已更改。

Example1.json:

输入标签值 - example1(这是json文件名)

输出标签值 - tags1(根据要求)

Example2.json

输入标签值 - example2(这是json文件名)

输出标签值 - tags2(根据要求)

输出Example1.json

{
  "info": {
    "title": "My example swagger 2",
    "version": "1.0"
  },
  "paths": {
    "/v1/resource3": {
        "get": {
            "description": "This is the example2",
            "tags": [
                "tag2"
            ],
            "consumes": [
                "*/*"
            ]
        }
    },
    "/v1/resource4": {
        "get": {
            "tags": [
                "tag2"
            ],
            "consumes": [
                "*/*"
            ]
       }
    }
  }
}

输出Example2.json

sed -i "s/$/ #removenewlines#/" %1 
sed -i ":a;N;$!ba;s/\n//g" %1
sed -i "s/\"tags\":\(.*\) \"%oldtagvalue%\"/\"tags\":\1 \"%newtagvalue%\"/g" %1
sed -i "s/ #removenewlines#/\n/g" %1

我在批处理脚本中编写了以下命令,但它无法正常工作

\(.*\)

由于sed不适用于多行,我将换行符更改为#removenewlines#并将所有内容移至单行(第1行和第2行)。在第3行中,我尝试使用通配符%oldtagvalue%和变量%newtagvalue%找到关键标记,然后用$ echo %1 $ example1.json $ echo %oldtagvalue% $ example1 $ echo %newtagvalue% $ tag1 替换它。在第4行,我正在格式化json。 上面的代码在循环中运行,因此对于变量的第一个循环值将是

$ echo %1 
$ example2.json
$ echo %oldtagvalue%
$ example2
$ echo %newtagvalue%
$ tag2

对于第二个循环值将是

awk

但它不起作用。请指教。我也尝试使用jq命令实现它,但它没有用。

2 个答案:

答案 0 :(得分:1)

因此,如果我理解正确,您希望替换具有文件名称的标签,并将其替换为您选择的标签。这是你可以做到的一种方式:

$ jq --arg newtag 'tag1' '(input_filename | sub("\\.json$"; "")) as $oldtag
    | .paths[][].tags |= map(if . == $oldtag then $newtag else . end)' example1.json

如果您想替换任意标签而不只是替换与文件名匹配的标签,只需添加另一个参数:

$ jq --arg oldtag 'example1' --arg newtag 'tag1' \
    '.paths[][].tags |= map(if . == $oldtag then $newtag else . end)' example1.json

如果您希望能够替换多个不同的标签,您可以创建一个对象,将旧标签映射到新标签并构建它。

$ jq --argjson tagmap '{"example1":"tag1","example2":"tag2"}' \
    '.paths[][].tags |= map($tagmap[.] // .)' example1.json

答案 1 :(得分:0)

这应该让你开始:

$ jq --arg tag "tag1" '
  .paths |= with_entries(.value.get.tags[] = $tag)' Example1.json

或者稍微不同,你可以使用这个过滤器:

# Apply f to composite entities recursively, and to atoms
def walk(f):
  . as $in
  | if type == "object" then
      reduce keys[] as $key
        ( {}; . + { ($key):  ($in[$key] | walk(f)) } ) | f
  elif type == "array" then map( walk(f) ) | f
  else f
  end;
walk(if type=="object" and has("tags") then .tags[] |= $tag else . end)

在这两种情况下,输出如下所示。你当然也可以改变"例如N"到" tagN"以编程方式在jq程序中(例如使用sub/2),如果这是你想要的。重要的是,只有jq才能完成这项工作。

{
  "info": {
    "title": "My example swagger 1",
    "version": "1.0"
  },
  "paths": {
    "/v1/resource1": {
      "get": {
        "description": "This is the example1",
        "tags": [
          "tag1"
        ],
        "consumes": [
          "*/*"
        ]
      }
    },
    "/v1/resource2": {
      "get": {
        "tags": [
          "tag1"
        ],
        "consumes": [
          "*/*"
        ]
      }
    }
  }
}