WOODY'S
FINDINGS

Read

This command outputs a single value (e.g. a string) or a group value (e.g. a dictionary) for a given path.

The examples on this page will refer to this JSON file that can be found in the playground (you might want to copy/paste or to download it somewhere to keep it in sight).
Note that any of the four People files could be used. Thus the examples are not always using a Json explorer.

{
  "Tom" : {
    "age" : 68,
    "hobbies" : [
      "cooking",
      "guitar"
    ],
    "height" : 175
  },
  "Robert" : {
    "age" : 23,
    "hobbies" : [
      "video games",
      "party",
      "tennis"
    ],
    "running_records" : [
      [
        10,
        12, 9,
        10
      ],
      [ 9,
        12,
        11
      ]
    ],
    "height" : 181
  },
  "Suzanne" : {
    "job" : "actress",
    "movies" : [
      {
        "title" : "Tomorrow is so far",
        "awards" : "Best speech for a silent movie"
      },
      {
        "title" : "Yesterday will never go",
        "awards" : "Best title"
      },
      {
        "title" : "What about today?"
      }
    ]
  }
}


Simple example

Read Tom's height.

Use the option -i|--input to specify a file as input. Otherwise Scout can read the input stream.

scout read -i People.json -f json "Tom.height"
In the next examples, the option -i People.json -f json will be implicitly specified.


Get a group value

Read Tom's dictionary

scout read "Tom"
will output
{
  "age" : 68,
  "hobbies" : [
    "cooking",
    "guitar"
  ],
  "height" : 175
}

Common

Invalid paths

If the path is invalid, the command will return/throw an error with a proper message. A path can be invalid for several reasons. For instance:

This command will return an error because the key "score" does not exist in Tom's dictionary.

scout read "Tom.score"
When that's possible, the program will display a message to offer another possible key name. For instance the command
scout read "Tom.heiht"
will return an error but will also inform that the key 'height' is near the 'heiht' word.


Array subscripting

It's possible to access an element in an array by specifying its index.
When the index is negative, this targets an element starting from the end of the array.
This figure gives an example with the 'ducks' array.

["Riri", "Fifi", "Loulou", "Donald", "Daisy"]
[  0   ,   1   ,    2    ,    3    ,    4   ] (Positive)
[ -5   ,  -4   ,   -3    ,   -2    ,   -1   ] (Negative)

Targets Robert's second hobby.

scout read "Robert.hobbies[1]"
Targets Robert's last hobby.
scout read "Robert.hobbies[-1]"


Read command specificities

Count

It's possible to get an dictionary or an array count with the count [#] symbol.

Get Robert hobbies count.

scout read "Robert.hobbies[#]"
Get people count.
scout read "[#]"


Keys symbol

List the keys of a dictionary with the keys list {#} symbol.

Get the keys of the Suzanne's dictionary.

scout read "Suzanne{#}"
Output
[
  "job",
  "movies"
]


Array slicing

It's possible to target a slice of an array from a lower bound to an upper bound. The upper bound is included.
When a array is sliced, it's possible to continue the path with a next element that elements in the slice have in common.

A slice is specified with square brackets and a double point ':' between the bounds: '[lower:upper]'. No lower means 0 like [:10] and no upper means the last index like [10:].
Use a negative index to target the last nth elements like [-4:] to target the last 4 elements or [-4: -2] to target from the last fourth to the last second element. Get Robert's first two hobbies

scout read "Robert.hobbies[:1]"
Output:
[
  "video games",
  "party"
]
Get Suzanne's movies titles.
scout read "Suzanne.movies[:].title"
Output:
[
  "Tomorrow is so far",
  "Yesterday will never go",
  "What about today?"
]


Keys filtering

It's possible to target specific keys in a dictionary with a regular expression.
When a dictionary is filtered, it's possible to continue the path with a next element that elements in the slice have in common.
If the provided regular expression is invalid, an error will be thrown/returned.

This element is enclosed by sharp '#' signs. For instance #.*device.*# to target all the keys in a dictionary containing the word device.
Get Tom keys that start with 'h'.

scout read "Tom.#h.*#"
Output:
{
  "hobbies" : [
    "cooking",
    "guitar"
  ],
  "height" : 175
}
Get Tom and Robert first hobby.
scout read "#Tom|Robert#.hobbies[0]"
Output:
{
  "Robert_hobbies_index(0)" : "video games",
  "Tom_hobbies_index(0)" : "cooking"
}


Mixing

It's possible to mix the array slicing and dictionary filtering features.

Get Tom and Robert first two hobbies.

scout read "#Tom|Robert#.hobbies[:1]"
Output:
{
  "Tom" : [
    "cooking",
    "guitar"
  ],
  "Robert" : [
    "video games",
    "party"
  ]
}


Zsh arrays

Scout allows to read a Zsh array directly from an array or dictionary.
To get a 1-dimension array from the data, the option —export|-e can be used with the array option and by enclosing the result with brackets.

hobbies=("${(@f)$(scout read -i People.json -f json "Robert.hobbies" -e array)}")
echo $hobbies[1] # video games
The same goes for dictionaries to associative arrays with the dictionary option.
declare -A movie=("${(@f)$(scout read -i People.json -f json "Suzanne.movies[0]" -e dictionary)}")
echo $movie[title] # Tomorrow is so far

XML attributes

When working with XML and the read features, Scout will allow to read an attribute with a key element from 4.0.0.

For instance with the following XML.

<Tom score="20">
    <height>175</height>
    <age>68</age>
</Tom>

It’s possible to read the score value.

scout read -i File.json -f json "Tom.score"
<Tom score="20">
    <height>175</height>
    <age>68</age>
</Tom>

The following will output 20

scout read -i File.json -f json "Tom.score"

When the following will output 68.

scout read -i File.json -f json "Tom.[1]"