chizou
chizou

Reputation: 1282

How to use jq to filter an array with elements of mixed type

Given the below JSON, I'm trying to select all the command elements. My issue is that the "checkout" string is messing up my selection of all the "run" dicts.

I'm trying to pass jq something like .[].run.command but I keep getting the error jq: error (at <stdin>:33): Cannot index string with string "run"

How do I exclude the "checkout" string from being selected?

[
  "checkout",
  {
    "run": {
      "command": "pip install cfn-lint pycodestyle pyflakes",
      "name": "Install Dependencies"
    }
  },
  {
    "run": {
      "command": "find stacks -type f -name \"*.yml\" -exec cfn-lint -i E3016 -i E3012 -i E1029 --template {} \\; | tee -a output.txt",
      "name": "Run cfn-lint"
    }
},
  {
    "run": {
      "command": "find stacks -type f -name \"*.py\" -exec pyflakes {} \\; | tee -a output.txt",
      "name": "Run pyflakes"
    }
  },
  {
    "run": {
      "command": "pycodestyle --show-source --show-pep8 --ignore=E501,W605 stacks/src | tee -a output.txt",
      "name": "Run pycodestyle"
    }
  },
  {
    "run": {
      "command": "if [[ -s output.txt ]]; then cat output.txt; exit 1; fi",
      "name": "Exit if there are validation warnings/errors"
    }
  }
]

Upvotes: 3

Views: 631

Answers (2)

Jeff Mercado
Jeff Mercado

Reputation: 134611

If you're dealing with sets of those kinds of arrays with a fixed structure where the first item is like an alias followed by a bunch of actions, you could just skip the first item and process the rest.

.[1:][].run.command

Otherwise if it is truly mixed and any item can be anything, some sort of filtering would have to be done as peak outlines.

Upvotes: 2

peak
peak

Reputation: 117027

Here's a solution that is a simple variation of the filter you've shown:

.[].run?.command

The "?" is syntactic sugar for a try wrapper.

Here's another variation, which suggests still others:

.[] | objects | .run.command

Upvotes: 3

Related Questions