【问题标题】:How to create JSON Array in Bash如何在 Bash 中创建 JSON 数组
【发布时间】:2019-09-23 15:10:09
【问题描述】:

我想为 emr 步骤创建 JSON 数组。我已经为单个 json 字符串创建了数组。这是我的 bash 代码 -

export source="s3a://sourcebucket"
export destination="s3a://destinationbucket"

EMR_DISTCP_STEPS=$( jq -n \
                  --arg source "$source" \
                  --arg destination "$destination" \
                  '{
                    "Name":"S3DistCp step",
                    "HadoopJarStep": {
                    "Args":["s3-dist-cp","--s3Endpoint=s3.amazonaws.com", "'"--src=${sourcepath}"'" ,"'"--dest=${destinationpath}"'"],
                    "Jar":"command-runner.jar"
                    },
                     "ActionOnFailure":"CONTINUE"
                   }' )

输出

echo $EMR_DISTCP_STEPS

[{ "Name": "S3DistCp step", "HadoopJarStep": { "Args": [ "s3-dist-cp", "--s3Endpoint=s3.amazonaws.com", "--src=s3a://sourcebucket", "--dest=s3a://destinationbucket" ], "Jar": "command-runner.jar" }, "ActionOnFailure": "CONTINUE" }]

现在我想创建具有多个源和目标的 JSON 数组 输出

[{ "Name": "S3DistCp step", "HadoopJarStep": { "Args": [ "s3-dist-cp", "--s3Endpoint=s3.amazonaws.com", "--src=s3a://sourcebucket1", "--dest=s3a://destinationbucket1" ], "Jar": "command-runner.jar" }, "ActionOnFailure": "CONTINUE" },
{ "Name": "S3DistCp step", "HadoopJarStep": { "Args": [ "s3-dist-cp", "--s3Endpoint=s3.amazonaws.com", "--src=s3a://sourcebucket2", "--dest=s3a://destinationbucket2" ], "Jar": "command-runner.jar" }, "ActionOnFailure": "CONTINUE" },
{ "Name": "S3DistCp step", "HadoopJarStep": { "Args": [ "s3-dist-cp", "--s3Endpoint=s3.amazonaws.com", "--src=s3a://sourcebucket3", "--dest=s3a://destinationbucket3" ], "Jar": "command-runner.jar" }, "ActionOnFailure": "CONTINUE" }]

如何在 Bash 中生成具有多个源和目标(JSON 字符串)的 JSON 数组?

【问题讨论】:

  • 这三个项目是否应该以任何方式彼此不同?如果是这样,用于区分它们的数据应该来自哪里?
  • 顺便说一句,请注意,您不想将 syntactic 引号与 literal 引号混为一谈。也就是说,在包含参数'foo' 的shell 命令中,引用'对你的shell 的指令,而不是参数foo 的一部分,你想把它省略掉任何 JSON 或其他更高级别的数据表示。
  • 考虑将你的 bash 脚本转换成 python - 你会避免很多陷阱。
  • @mvp, ...我完全同意能够表示您试图在内存中操作的结构的语言(以及符合相关格式规范的解析/生成设施)是处理结构化数据的正确工具。也就是说,jq 这样的语言,就像 Python 一样,并且恰好已经在问题中标记。 :)
  • @lucy, ...顺便说一下,关于变量名的注释——POSIX 指定全大写名称保留给修改 POSIX 定义的实用程序(和/或外壳程序)行为的变量本身),而小写名称保留给应用程序使用,并保证不会修改兼容工具的行为。由于非导出的 shell 变量会修改任何预先存在的同名环境变量,因此本指南适用于这两种类型;见pubs.opengroup.org/onlinepubs/9699919799/basedefs/…,第四段。

标签: bash jq amazon-emr ash


【解决方案1】:

一种方法是提供一个jq 函数,该函数会根据您要修改的特定输入生成重复结构。考虑以下几点:

# generate this however you want to -- hardcoded, built by a loop, whatever.
source_dest_pairs=(
  sourcebucket1:destinationbucket1
  sourcebucket2:destinationbucket2
  sourcebucket3:destinationbucket3
)

# -R accepts plain text, not JSON, as input; -n doesn't read any input automatically
# ...but instead lets "inputs" or "input" be used later in your jq code.
jq -Rn '
  def instructionsForPair($source; $dest): {
    "Name":"S3DistCp step",
    "HadoopJarStep": {
      "Args":[
        "s3-dist-cp",
        "--s3Endpoint=s3.amazonaws.com",
        "--src=\($source)",
        "--dest=\($dest)"
      ],
      "Jar":"command-runner.jar"
    }
  };

  [ inputs 
  | capture("^(?<source>[^:]+):(?<dest>.*)$"; "")
  | select(.)
  | instructionsForPair(.source; .dest) ]
' < <(printf '%s\n' "${source_dest_pairs[@]}")

...正确地作为输出发出:

[
  {
    "Name": "S3DistCp step",
    "HadoopJarStep": {
      "Args": [
        "s3-dist-cp",
        "--s3Endpoint=s3.amazonaws.com",
        "--src=sourcebucket1",
        "--dest=destinationbucket1"
      ],
      "Jar": "command-runner.jar"
    }
  },
  {
    "Name": "S3DistCp step",
    "HadoopJarStep": {
      "Args": [
        "s3-dist-cp",
        "--s3Endpoint=s3.amazonaws.com",
        "--src=sourcebucket2",
        "--dest=destinationbucket2"
      ],
      "Jar": "command-runner.jar"
    }
  },
  {
    "Name": "S3DistCp step",
    "HadoopJarStep": {
      "Args": [
        "s3-dist-cp",
        "--s3Endpoint=s3.amazonaws.com",
        "--src=sourcebucket3",
        "--dest=destinationbucket3"
      ],
      "Jar": "command-runner.jar"
    }
  }
]

【讨论】:

  • 运行上述脚本时出现此错误syntax error near unexpected token &lt;'
  • @DucTran,确保使用bash 而非sh 运行它
  • 我尝试更改命令的顺序,然后它起作用了。比如:printf ... | jq -Rn ...
  • @DucTran,即使它不是 POSIX sh 的一部分(因此只能与支持 process substitution 的 bash 和其他 shell 一起使用),&lt;(...) 语法更好,原因是描述的在BashFAQ #24.
  • 谢谢,我用bash成功运行了原始脚本。
猜你喜欢
  • 2015-06-07
  • 1970-01-01
  • 2018-04-28
  • 1970-01-01
  • 2023-02-23
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多