Is there a way to just replace the X instance or give it a specific line to replace?
Если бы это был я, я бы использовал модуль shell
и стандартный вызов sed
для изменения в определенной строке. В приведенном ниже примере я использую sed
, чтобы изменить только четвертую строку.
---
- hosts: all
tasks:
- name: "Run sed via ansible"
shell: sed -i '4s/bike/car/' /home/maulinglawns/slask/sed_example
Пример файла перед ansible playbook:
cat sed_example
bike plane
bike plane
bike plane
bike plane
bike plane
bike plane
bike plane
bike plane
bike plane
bike plane
Запуск пьесы:
ansible-playbook sed_with_ansible.yml -i "localhost," -k
SSH password:
PLAY [all] *********************************************************************
TASK [setup] *******************************************************************
ok: [localhost]
TASK [Run sed via ansible] *****************************************************
changed: [localhost]
[WARNING]: Consider using template or lineinfile module rather than running
sed
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0
Файл после плейбука:
cat sed_example
bike plane
bike plane
bike plane
car plane
bike plane
bike plane
bike plane
bike plane
bike plane
bike plane
Вы могли бы добиться этого с помощью модуля lineinfile
, но я не знаю ни одного такого переключателя и не смог найти его в документации.
В принципе, с этими точными переменными можно было бы использоватьenvsubst
:
$ export env_var1=val1
$ export env_var2=val2
$ export args='{"key1": "${env_var1}", "key2": "${env_var2}"}'
$ echo "$args" | envsubst
{"key1": "val1", "key2": "val2"}
Но обратите внимание, что a )будет расширять любые переменные среды, а не только те, которые соответствуют env_*
, а b )не будет заключать в кавычки какое-либо содержимое, чтобы преобразовать его в действительный JSON. Например. с env_var1='double"quote'
вы получите {"key1": "double"quote",...
с нарушенным цитированием.
Чтобы решить эту первую проблему, вы можете сделать что-то подобное в Bash, чтобы получить строку, содержащую список имен переменных, соответствующих env_*
-envsubst
:
$ echo "$args" | envsubst "$(printf '$%s ' "${!env_@}")"
{"key1": "val1", "key2": "val2"}
(проблема в том, что для этого требуются начальные $
знаки.)
Во-вторых, вам нужно предварительно обработать переменные перед их передачей в envsubst
или передать их через jq
.
Что-то вроде этого будет генерировать --arg
опции для jq
для всех переменных с именами типа env_*
и изменять любые "${foo}"
из входной строки на $foo
, чтобы jq
распознавал их как переменные (. ] обратите внимание, что это также изменит любые несвязанные совпадающие строки):
#!/bin/bash
args=();
for varname in "${!env_@}"; do
args+=(--arg "$varname" "${!varname}");
done;
jq -n -c -M "${args[@]}" "$(sed -E -e 's/"\$\{([a-zA-Z0-9_]+)\}"/$\1/g' <<< "$1")"
Выполнить с помощью:
$ export env_var1='double"quote' env_var2=foobar
$ bash jsonexpand.sh '{"key1": "${env_var1}", "key2": "${env_var2}"}'
{"key1":"double\"quote","key2":"foobar"}
Вам нужно заключить выражение в кавычки, чтобы оболочка не анализировала его. В тривиальном случае
echo '{"key1": "var1", "key2": "var2"}'
В вашем случае, когда нужна интерполяция переменных, подойдет любой из этих вариантов
printf '{"key1": "%s", "key2": "%s"}\n' "$env_var1" "$env_var2"
echo "{\"key1\": \"$env_var1\", \"key2\": \"$env_var2\"}"
echo '{"key1": "'"$env_var1"', "key2": "'"$env_var2"'"}'
Я бы, наверное, порекомендовал первый из них как наиболее читабельный.
Вы можете избежать кавычек:
{\"key1\": \""$env_var1"\", "key2": \""$env_var2"\"}
Вы можете использовать jq:
jq -n --arg one "$env_var1" --arg two "$env_var2" '{key1: $one, key2: $two}'
или жо:
jo key1="$env_var1" key2="$env_var2"
Я часто использую heredocs для сложных объектов json:
read -rd '' json <<EOF
{
key1: "$env_var1",
key2: "$env_var2"
}
EOF
echo "$json"