Reputation: 2471
I have a simple list of hostnames such as:
hostname1,hostname2,hostname3
(Note: the format of the YAML file can be changed for easier parsing if necessary)
I need to be able to loop over this list of hostnames in both python and bash.
A simple indexed array will work for this purpose since the only property is hostname and the list will never be more than 1 level deep.
I know can easily parse this with Python with the code I started below.
How can I also parse this as a Bash array?
Python 2.7
import yaml
with open('emc_hosts.yaml', 'r') as f:
doc = yaml.load(f)
doc = doc.split(",")
for v in doc:
print(v)
UPDATE: The hostnames are all on the same line, but they don't have to be. I can create the hostname file in any format that I want including separated by return or other characters.
UPDATE 2: The file will only contain a list of hostnames.
UPDATE 3: As per a suggestion in the comments, I could easily change this from a YAML file to a simple text file with hostnames separated by new lines.
Upvotes: 1
Views: 2496
Reputation: 127
You can parse yaml/json file directly in your shell/bash with niet.
Easy to install and easy to use:
$ pip install -U niet
Consider the following example:
$ cat dump.yaml
foo:
bar:
key: value
baz:
key: value
tags:
- one
- two
You can parse this example file like this:
$ niet dump.yaml foo.bar.key
value
$ for el in $(niet dump.yaml foo.tags); do echo ${el}; done
one
two
Niet have a good integration with shell and others bash like.
Niet yaml parser documentation, source code, and samples.
Also Niet is developing using python.
Upvotes: 3
Reputation: 295706
If you already have working Python code, might as well use it.
# Embed your Python script into your bash code
_get_hosts_python=$(cat <<'EOF'
import yaml, sys
with open(sys.argv[1], "r") as f:
doc = yaml.load(f)
doc = doc.split(",")
for v in doc:
print(v)
EOF
)
# provide a function to wrap its invocation
get_hosts() {
IFS=$'\n' read -r -d '' -a "${1:-hosts}" \
< <(python -c "$_get_hosts_python" "emc_hosts.yml" && printf '\0')
}
# and demonstrate how to actually use that function
get_hosts hostlist
echo "Got ${#hostlist[@]} hosts:"
printf '- %s\n' "${hostlist[@]}"
Note that bash 4.0 and newer have readarray
and mapfile
commands, which can be used to read a stream of lines into an array; I didn't use them here because it requires bash 4.4 to check the exit status of a process substitution (the <( ... )
syntax), so we wouldn't be able to detect errors if we went that approach (whereas here, the && printf \0'
ensures that the stream has a trailing NUL -- and thus that the read
has a successful exit status -- only if the Python code exited with a successful exit status).
Upvotes: 2