If the YAML file isn't too big, you could use Bash code to make the edits in memory and write the results back to the file. This, Shellcheck-clean, code demonstrates the idea:
#! /bin/bash -p
# Set passwords in a YAML file. Update the file in place.
function set_yaml_passwords
{
local -r yaml_file=$1
# Create a regular expression to match key/password lines
local -r key_rx='^([[:space:]]*key[[:digit:]]*:[[:space:]]*)'
local -r pw_rx='__[[:alnum:]]*[Pp]assword[[:alnum:]]*__[[:space:]]*$'
local -r key_pw_rx=${key_rx}${pw_rx}
# Read the YAML file lines into an array, setting passwords as we go
local yaml_lines=() is_updated=0
local line keystring newpw
while IFS= read -r line || [[ -n $line ]] ; do
if [[ $line =~ $key_pw_rx ]] ; then
keystring=${BASH_REMATCH[1]}
newpw=$(pwgen 10)
yaml_lines+=( "${keystring}${newpw}" )
is_updated=1
else
yaml_lines+=( "$line" )
fi
done <"$yaml_file"
# If any passwords have been set, update the YAML file
if (( is_updated )) ; then
printf '%s\n' "${yaml_lines[@]}" >"$yaml_file"
printf "Updated '%s'\\n" "$yaml_file" >&2
fi
return 0
}
set_yaml_passwords 'temp.yaml'
This is an example of a YAML file produced by running the code above on the example YAML file given in the question:
# Comment shouldn't be deleted
passwords:
key1: yai9cegiD4
key2: Ahtah1eyoh
key3: ya1teo1ooB
key4: AhGae5EiLe
# All comments should be preserved
passwords-new:
key1: oaKoh0teiK
- Line-by-line processing in Bash code is very slow. The code above took almost 1 second to process a ten thousand line file (with a small number of key/password lines) on my (oldish) Linux system. On a modern system you'll run into time problems long before you run into memory problems.
- I used
pwgen 10
to generate new passwords. You may want to do something else.
- There's no error checking in the demonstration code. Real code should check for missing file, unreadable file, unwritable file, wrong number of arguments to the function, etc.