繁体   English   中英

jq json object 串联到 bash 字符串数组

[英]jq json object concatenation to bash string array

我想使用jq (或其他任何工具,当它是错误的工具时)连接一个 json object 像这样:

{
  "https://github.com": {
    "user-one": {
      "repository-one": "version-one",
      "repository-two": "version-two"
    },
    "user-two": {
      "repository-three": "version-three",
      "repository-four": "version-four"
    }
  },
  "https://gitlab.com": {
    "user-three": {
      "repository-five": "version-five",
      "repository-six": "version-six"
    },
    "user-four": {
      "repository-seven": "version-seven",
      "repository-eight": "version-eight"
    }
  }
}

递归到 bash 字符串数组,如下所示:

(
    "https://github.com/user-one/repository-one/archive/refs/heads/version-one.tar.gz"
    "https://github.com/user-one/repository-two/archive/refs/heads/version-two.tar.gz"
    "https://github.com/user-two/repository-three/archive/refs/heads/version-three.tar.gz"
    "https://github.com/user-two/repository-four/archive/refs/heads/version-four.tar.gz"
    "https://gitlab.com/user-three/repository-five/-/archive/version-five/repository-five-version-five.tar.gz"
    "https://gitlab.com/user-three/repository-six/-/archive/version-six/repository-six-version-six.tar.gz"
    "https://gitlab.com/user-four/repository-seven/-/archive/version-seven/repository-seven-version-seven.tar.gz"
    "https://gitlab.com/user-four/repository-eight/-/archive/version-eight/repository-eight-version-eight.tar.gz"
)

供后续循环使用。

for i in "${arr[@]}"
do
   echo "$i"
done

不知道该怎么做。 如您所见,必须根据 object 名称对这些值进行不同的处理。

"https://github.com" + "/" + $user_name + "/" + $repository_name + "/archive/refs/heads/" + $version + ".tar.gz"

"https://gitlab.com" + "/" + $user_name + "/" + $repository_name + "/-/archive/" + $version + "/" + $repository_name + "-" + $version + ".tar.gz"

有人可以帮忙吗?

轻松搞定。

首先,我们只关注jq代码:

to_entries[]                # split items into keys and values
| .key as $site             # store first key in $site
| .value                    # code below deals with the value
| to_entries[]              # split that value into keys and values
| .key as $user             # store the key in $user
| .value                    # code below deals with the value
| to_entries[]              # split that value into keys and values
| .key as $repository_name  # store the key in $repository_name
| .value as $version        # store the value in $version
| if $site == "https://github.com" then
    "\($site)/\($user)/\($repository_name)/archive/refs/heads/\($version).tar.gz"
  else
    "\($site)/\($user)/\($repository_name)/-/archive/\($version)/\($repository_name)-\($version).tar.gz"
  end

这会生成一个行列表。 将行读入 bash 数组看起来像readarray -t arrayname <...datasource...

因此,使用进程替换来重定向 jq 的标准输出,就好像它是一个文件一样:

readarray -t uris < <(jq -r '
  to_entries[]
  | .key as $site
  | .value
  | to_entries[]
  | .key as $user
  | .value
  | to_entries[]
  | .key as $repository_name
  | .value as $version
  | if $site == "https://github.com" then
      "\($site)/\($user)/\($repository_name)/archive/refs/heads/\($version).tar.gz"
    else
      "\($site)/\($user)/\($repository_name)/-/archive/\($version)/\($repository_name)-\($version).tar.gz"
    end
  ' <config.json
)

使用 jq 过滤器可以高效且通用地完成生成字符串的基本任务(即,对基本名称的深度没有任何限制):

paths(strings) as $p | $p + [getpath($p)] | join("/")

有几种方法可以相应地填充 bash 数组,但如果您只想遍历这些值,则可以使用 bash while循环,如下所示:

< input.json jq -r '
  paths(strings) as $p | $p + [getpath($p)] | join("/")' | 
  while read -r line ; do
    echo "$line"
  done

您可能还希望考虑使用 jq 的 @sh 或 @uri 过滤器。 对于 jq urlencode function,参见例如https://rosettacode.org/wiki/URL_encoding#jq

(如果字符串包含换行符或制表符,则需要相应地调整上述内容。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM