строковая интерполяция с сохранением кавычек в bash

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, но я не знаю ни одного такого переключателя и не смог найти его в документации.

1
02.06.2021, 23:44
3 ответа

В принципе, с этими точными переменными можно было бы использовать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"}
2
28.07.2021, 11:27

Вам нужно заключить выражение в кавычки, чтобы оболочка не анализировала его. В тривиальном случае

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"'"}'

Я бы, наверное, порекомендовал первый из них как наиболее читабельный.

1
28.07.2021, 11:27

Вы можете избежать кавычек:

{\"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"
2
28.07.2021, 11:27

Теги

Похожие вопросы