I was waiting until you accepted another answer to write this, as it adds a dependency on yq
from https://kislyuk.github.io/yq/
#!/bin/bash
unset mic
unset speaker
while getopts m:s: opt; do
case $opt in
m)
mic=$OPTARG
;;
s)
speaker=$OPTARG
;;
*)
echo 'invalid option' >&2
exit 1
esac
done
shift "$(( OPTIND - 1 ))"
yaml_update () {
key=${1,,} # lower-case, e.g. "mic"
Key=${key^?} # title-case, e.g. "Mic"
value=$2
yq -Y --arg key "$key" --arg Key "$Key" --arg value "$value" '
(select(.name == $key).components[] |
select(.name == $Key).parameters.alsa_device_name) |= $value'
}
if [ "${mic+set}" = "set" ]; then
yaml_update mic "$mic"
else
cat -
fi |
if [ "${speaker+set}" = "set" ]; then
yaml_update speaker "$speaker"
else
cat -
fi
Most of the code in the script is command line parsing and logic related to the given command line options. This was due to a requirement, or at least a suggestion, in the question to be able to use the solution with a set of convenient options on the command line. The actual code that does something is in the yaml_update
function and consists of three lines of code (the yq
command, and it's only three lines because it would be too long on a single line).
This script would be used like so:
./script -m logitec -s hk34 <file.yaml >file-new.yaml
It takes two optional command line options, -m
and -s
(long options, suggested in the question, are not standard and not supported by the getopts
built-in in bash
) to set the mic and/or the speaker Alsa device name respectively.
The YAML document is read on standard input and the resulting document is written to standard output.
The update is done with yq
using an expression that selects the correct top-level object based on the name
key, and then the correct array element from the components
array using its name
key. It then updates the alsa_device_name
value under the selected elements' parameters
key.
For convenience, the yq
call was moved into a shell function (we're potentially doing two extremely similar calls to yq
, so this seemed reasonable).
The output, if changing the given document like shown above, would be
name: mic
components:
- name: Mic
parameters:
period_count: 4
alsa_device_name: "logitec"
---
name: speaker
components:
- name: Speaker
parameters:
period_duration_ms: 20
period_count: 4
alsa_device_name: "hk34"
awk
orsed
.%YAML 1.2
makes your input incompatible to YAML grammarmic
andalsa_device_name
. Can you give me some hintsed
is OK? Can we use any other standard utilities likeperl
orawk
all of which will be installed on a Linux system?