带有使 JQ 失败的控制代码的 AWS CLI returns JSON

AWS CLI returns JSON with control codes making JQ fail

我已经多次使用 jq 从 AWS CLI 返回的 JSON 中解析、选取值等,例如对于 ec2 describe-instances 等等

现在我正在使用 dockerized version of AWS CLI v2 获取 CloudWatch 日志组列表:

$ alias aws='docker run --rm -it -v ~/.aws:/root/.aws -e AWS_PROFILE -e AWS_REGION amazon/aws-cli'
$ aws logs describe-log-groups

{
    "logGroups": [
        {
            ...
        }
    ]
}

这看起来很合适JSON;然而,当将其传送到 jq 时,我得到:

parse error: Invalid numeric literal at line 1, column 2

如果在二进制编辑器中查看从 aws 返回的 JSON,或者使用 jq:s inputs 功能,我发现它包含很多控制代码:

[
  "\u001b[?1h\u001b=\r{\u001b[m\r",
  "    \"logGroups\": [\u001b[m\r",
  "        {\u001b[m\r",
  "            \"logGroupName\": \"/aws/lambda/...
...

在我看来,是我通过 docker 使用 AWS CLI 导致了这一点,因为当使用使用 pip 安装的老式 AWS CLI v1 时,它不会发生- 但它也可能是 v2 与 v1 的关键区别,而不是使用 docker 作为我猜的环境(我从未尝试过本地安装 v2)。

这些控制代码,例如\u001b[m,看起来像 ANSI 代码来控制格式,例如粗体、颜色等。但是据我所知,AWS CLI 不使用 colored/ANSI 输出。为什么它们包含在返回的 JSON 中?是否有一个简单的工具可以去除它们,以便我可以继续使用 docker 化的 AWS CLI v2 并将输出通过管道传输到 jq?我使用复杂的 sed 模式找到了其他答案,我心想一定有更简单的方法来做到这一点?

Edit:这是一个使用 xxd 显示控制代码的最小示例。我故意列出具有不匹配过滤器的日志组以获得空数组:

$ aws logs describe-log-groups --log-group-name-prefix FOO > foo.txt
$ xxd foo.txt
00000000: 1b5b 3f31 681b 3d0d 7b1b 5b6d 0d0a 2020  .[?1h.=.{.[m..  
00000010: 2020 226c 6f67 4772 6f75 7073 223a 205b    "logGroups": [
00000020: 5d1b 5b6d 0d0a 7d1b 5b6d 0d0a 0d1b 5b4b  ].[m..}.[m....[K
00000030: 1b5b 3f31 6c1b 3e                        .[?1l.>
$ cat foo.txt | jq
parse error: Invalid numeric literal at line 1, column 2
                                                        $

使用非docker化的 AWS CLI v1 时 xxd 显示相同的内容:

00000000: 7b0a 2020 2020 226c 6f67 4772 6f75 7073  {.    "logGroups
00000010: 223a 205b 5d0a 7d0a                      ": [].}.

aws CLI 将其输出提供给 less,因为 a) 您已经分配了一个带有 -it 标志的伪终端,b) 就进程而言关注的是,它直接输出到 tty 而不是管道,并且 c) 你没有 told it do anything else instead. The correct fix is to remove -it - it's only there for when you need to provide interactive input,如果你将输出通过管道传输到 jq 那么你不需要或不想要交互式输入。但是,如果您尝试设置别名或函数以无缝代替 aws,您需要根据是否需要交互式输入来决定是否传递 -it。你可以试试这个:

function daws() {
    local usetty
    if [ -t 1 ]
    then
        usetty=-it
    else
        usetty=
    fi
    docker run --rm $usetty -v ~/.aws:/root/.aws -e AWS_PROFILE -e AWS_REGION amazon/aws-cli "$@"
}

并且在一行中:

function daws() { local usetty; if [ -t 1 ]; then usetty=-it; else usetty=; fi; docker run --rm $usetty -v ~/.aws:/root/.aws -e AWS_PROFILE -e AWS_REGION amazon/aws-cli "$@"; }

或者您可以传递 --no-cli-pager 或将环境变量 AWS_PAGER 设置为 cat,但我都试过了,虽然它们没有导致任何错误,但仍有一些错误奇怪的混乱输出,其中换行符没有为部分输出应用回车-return。