如何从包含编码 JSON 对象的 JSON 文件中提取值

如何从包含编码 JSON 对象的 JSON 文件中提取值

该命令 输出:aws s3api get-bucket-policy --bucket bucketname

{
    "Policy": "{\"Version\":\"2012-10-17\",\"Id\":\"S3SecureTransportPolicy\",\"Statement\":[{\"Sid\":\"ForceSSLOnlyAccess\",\"Effect\":\"Deny\",\"Principal\":{\"AWS\":\"*\"},\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::amn/*\",\"Condition\":{\"Bool\":{\"aws:SecureTransport\":\"false\"}}},{\"Sid\":\"AWSCloudTrailAclCheck20150319\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"cloudtrail.amazonaws.com\"},\"Action\":\"s3:GetBucketAcl\",\"Resource\":\"arn:aws:s3:::amn\"},{\"Sid\":\"AWSCloudTrailWrite20150319\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"cloudtrail.amazonaws.com\"},\"Action\":\"s3:PutObject\",\"Resource\":\"arn:aws:s3:::amn/AWSLogs/405042254276/*\",\"Condition\":{\"StringEquals\":{\"s3:x-amz-acl\":\"bucket-owner-full-control\"}}}]}"
}

我需要从这个 JSON 中 grep(即提取)与键关联的值aws:SecureTransport(在本例中为false)以及与键关联的值Effect

我试过了

aws s3api get-bucket-policy --bucket amn |
    grep -Po '"Bool": *\K"[^"]*"'

aws s3api get-bucket-policy --bucket amn |
    sed 's/.*\(aws:SecureTransport\)[^:]*:"\([0-9]*\)"'

我怎样才能做到这一点?

答案1

从命令中获取的 JSON 文档似乎包含另一个编码的 JSON 文档。您似乎想要从这个编码文档中获取数据。

要获取内部文档,我们可以使用jq

aws ... |
jq -r '.Policy'

Effect为了从包含该键的位中获取键的值aws:SecureTransport,我们需要再次解析文档:

aws ... |
jq -r '.Policy' |
jq -r '.Statement[] | select(.Condition.Bool."aws:SecureTransport").Effect'

最后一次jq调用将遍历数组的所有元素Statement,查找具有名为 的键的元素.Condition.Bool."aws:SecureTransport"。然后它获取Effect与该元素关联的键的值Statement

对您的数据运行此输出值Deny

.Condition.Bool."aws:SecureTransport"如果您想要该键的值(false在您的文档中),请使用.Condition.Bool."aws:SecureTransport"上面的内容.Effect

或者,使用fromjson指令jq代替第二次jq调用:

aws ... |
jq -r '.Policy | fromjson | .Statement[] | select(.Condition.Bool."aws:SecureTransport").Effect'

在这里,fromjson对编码的 JSON 文档进行解码并将其传递到后期处理阶段。


仅供参考,内部编码的 JSON 文档如下所示 ( aws ... | jq -r '.Policy | fromjson'):

{
  "Version": "2012-10-17",
  "Id": "S3SecureTransportPolicy",
  "Statement": [
    {
      "Sid": "ForceSSLOnlyAccess",
      "Effect": "Deny",
      "Principal": {
        "AWS": "*"
      },
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::amn/*",
      "Condition": {
        "Bool": {
          "aws:SecureTransport": "false"
        }
      }
    },
    {
      "Sid": "AWSCloudTrailAclCheck20150319",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Action": "s3:GetBucketAcl",
      "Resource": "arn:aws:s3:::amn"
    },
    {
      "Sid": "AWSCloudTrailWrite20150319",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::amn/AWSLogs/405042254276/*",
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}

答案2

首先,不要这样做!jq按照中所述使用拘萨罗南达的回答。这是一个比摆弄正则表达式更强大的解决方案。也就是说,这是一种方法grep

aws ... | grep -oP 'aws:SecureTransport.":."\K.+?(?=\\")'

这将查找aws:SecureTransport,然后是任何字符(.;这比编写\\转义斜杠更简单),然后是".将\K丢弃到目前为止匹配的任何内容(因此匹配的部分aws:SecureTransport.":.")。然后,查找.+?后跟\"( ) 的最短字符串 ( (?=\\"))。

在包含示例输出的文件上运行此命令会给出:

$ grep -oP 'aws:SecureTransport.":."\K.+?(?=\\")' file
false

相关内容