Заменить переменные окружения в файле на их фактические значения?

FreeBSD также поддерживает FUSE.

Удивительно, но существует реализация EXT4 для FUSE. Не знаю, насколько стабильным он считается.

http://blog.ataboydesign.com/2014/04/23/freebsd-10-mounting-usb-drive-with-ext4-filesystem/

Есть переносной ext4fuse, но он доступен только для чтения . Должна быть возможность использовать ntfs-3g , что дает вам преимущество журналируемой файловой системы, но некоторые функции Unix могут быть недоступны или потребовать дополнительной настройки.

76
09.07.2016, 17:39
5 ответов

Могу ли я предложить свой сценарий для этого?

https://github.com/rydnr/set-square/blob/master/.templates/common-files/process-file.sh

#!/bin/bash /usr/local/bin/dry-wit
# Copyright 2016-today Automated Computing Machinery S.L.
# Distributed under the terms of the GNU General Public License v3

function usage() {
cat <<EOF
$SCRIPT_NAME -o|--output output input
$SCRIPT_NAME [-h|--help]
(c) 2016-today Automated Computing Machinery S.L.
    Distributed under the terms of the GNU General Public License v3

Processes a file, replacing any placeholders with the contents of the
environment variables, and stores the result in the specified output file.

Where:
    * input: the input file.
    * output: the output file.
Common flags:
    * -h | --help: Display this message.
    * -v: Increase the verbosity.
    * -vv: Increase the verbosity further.
    * -q | --quiet: Be silent.
EOF
}

# Requirements
function checkRequirements() {
  checkReq envsubst ENVSUBST_NOT_INSTALLED;
}

# Error messages
function defineErrors() {
  export INVALID_OPTION="Unrecognized option";
  export ENVSUBST_NOT_INSTALLED="envsubst is not installed";
  export NO_INPUT_FILE_SPECIFIED="The input file is mandatory";
  export NO_OUTPUT_FILE_SPECIFIED="The output file is mandatory";

  ERROR_MESSAGES=(\
    INVALID_OPTION \
    ENVSUBST_NOT_INSTALLED \
    NO_INPUT_FILE_SPECIFIED \
    NO_OUTPUT_FILE_SPECIFIED \
  );

  export ERROR_MESSAGES;
}

## Parses the input
## dry-wit hook
function parseInput() {

  local _flags=$(extractFlags $@);
  local _flagCount;
  local _currentCount;

  # Flags
  for _flag in ${_flags}; do
    _flagCount=$((_flagCount+1));
    case ${_flag} in
      -h | --help | -v | -vv | -q)
         shift;
         ;;
      -o | --output)
         shift;
         OUTPUT_FILE="${1}";
         shift;
         ;;
    esac
  done

  # Parameters
  if [[ -z ${INPUT_FILE} ]]; then
    INPUT_FILE="$1";
    shift;
  fi
}

## Checking input
## dry-wit hook
function checkInput() {

  local _flags=$(extractFlags $@);
  local _flagCount;
  local _currentCount;
  logDebug -n "Checking input";

  # Flags
  for _flag in ${_flags}; do
    _flagCount=$((_flagCount+1));
    case ${_flag} in
      -h | --help | -v | -vv | -q | --quiet)
         ;;
      -o | --output)
         ;;
      *) logDebugResult FAILURE "fail";
         exitWithErrorCode INVALID_OPTION ${_flag};
         ;;
    esac
  done

  if [[ -z ${INPUT_FILE} ]]; then
    logDebugResult FAILURE "fail";
    exitWithErrorCode NO_INPUT_FILE_SPECIFIED;
  fi

  if [[ -z ${OUTPUT_FILE} ]]; then
      logDebugResult FAILURE "fail";
      exitWithErrorCode NO_OUTPUT_FILE_SPECIFIED;
  fi
}

## Replaces any placeholders in given file.
## -> 1: The file to process.
## -> 2: The output file.
## <- 0 if the file is processed, 1 otherwise.
## <- RESULT: the path of the processed file.
function replace_placeholders() {
  local _file="${1}";
  local _output="${2}";
  local _rescode;
  local _env="$(IFS=" \t" env | awk -F'=' '{printf("%s=\"%s\" ", $1, $2);}')";
  local _envsubstDecl=$(echo -n "'"; IFS=" \t" env | cut -d'=' -f 1 | awk '{printf("${%s} ", $0);}'; echo -n "'";);

  echo "${_env} envsubst ${_envsubstDecl} < ${_file} > ${_output}" | sh;
  _rescode=$?;
  export RESULT="${_output}";
  return ${_rescode};
}

## Main logic
## dry-wit hook
function main() {
  replace_placeholders "${INPUT_FILE}" "${OUTPUT_FILE}";
}
# vim: syntax=sh ts=2 sw=2 sts=4 sr noet
1
20.08.2021, 12:03

Используйте функцию cmakeи configure_file.

Он копирует файл <input>в файл <output>и заменяет значения переменных, указанные как @VAR@или ${VAR}, в содержимом входного файла. Каждая ссылка на переменную будет заменена текущим значением переменной или пустой строкой, если переменная не определена.

1
20.08.2021, 12:03

Приведенная ниже команда заменяет все вхождения переменных среды формы $VARв файле.

compgen -e | xargs -I @ sh -c 'printf "s|\$%q\>|%q|g\n" "@" "$@"' | sed -f /dev/stdin input.file > output.file

Примечание. Синтаксис:sedнемного отличается в macOS:[[:>:]]для использования вместо \>.

Вот как это работает:

  • compgen -eперечисляет имена переменных среды без значений, например :
    HOME
    LANG
    PATH
    PWD
    ...
    
  • xargsперенаправляет вывод в оболочку, которая обрабатывает sedподстановочные команды через printfзаполнение значений переменных среды по пути :
    s|$HOME\>|/Users/sshymko|g
    s|$LANG\>|en_US.UTF-8|g
    s|$PATH\>|/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin|g
    s|$PWD\>|/Users/sshymko/Documents|g
    ...
    
  • sedизменяет содержимое файла с помощью подстановочных команд в стандартном вводе

Замещающий формат команды: s|\$%q\>|%q|g\n, где:

  • |— разделитель гарантированно экранируется в имени/значении переменной окружения
  • %q— строковый заменитель printf, экранирующий специальные символы оболочки
  • \>— конец границы слова , чтобы избежать совпадения префикса имени переменной
  • g— глобальная замена, т.е.заменить все вхождения
  • \n— разрыв строки, разделяющий sedподстановочные команды

Дополнительно:

  • @— аргумент-заполнитель xargs, содержащий имя переменной окружения
  • $@— разыменованное значение переменной окружения
1
20.08.2021, 12:03

Чтобы добавить к обсуждению образов Docker выше, (к сожалению, не смог прокомментировать ).

В качестве наиболее безопасных методов следует использовать либо envsubst, либо perl. При использовании в Docker проблема заключается в том, что последний является частью образов на основе Debian -(, включаяslim-типа ), но не Alpine. Добавление envsubstнепосредственно к образу приведет к увеличению размера на 25 МБ или 65 МБ в образах на базе Alpine или Debian -соответственно.

В результате я выбрал один из них напрямую в docker-entrypoint. Предупреждение :в образах на основе Alpine -, он загружает envsubstнепосредственно с Github. Возможно, вы захотите, чтобы он был где-то локально, чтобы ускорить процесс. Или запеките -на этапе сборки (всего 2,5 Мб таким образом ).

        # do not add `envsubst` to the image! It saves 25/65M in Docker Alpine/Debian-based images correspondingly
        # `perl` is part of Debian but not Alpine-based images
        if [[ -n $(command -v perl) ]] ; then
            perl -pe 's/\$(\w+)/$ENV{$1}/g' <"${file}" >"/tmp/${filename}"
        else
            if [[ ! -f /tmp/envsubst ]] ; then
                wget -O /tmp/envsubst "https://github.com/a8m/envsubst/releases/latest/download/envsubst-$(uname -s)-$(uname -m)"
                chmod 500 /tmp/envsubst
            fi
            /tmp/envsubst -i "${file}" -o "/tmp/${filename}"
        fi
...
[[ -f /tmp/envsubst ]] && rm -f /tmp/envsubst
1
20.08.2021, 12:03

Как и в случае с ответом Perl, подстановку переменных среды можно делегировать PHP CLI. Зависимость от PHP может быть приемлемой или неприемлемой в зависимости от используемого технического стека.

php -r 'echo preg_replace_callback("/\\$([a-z0-9_]+)/i", function ($matches) { return getenv($matches[1]); }, fread(STDIN, 8192));' < input.file > output.file

Можно пойти дальше и поместить его в многоразовый скрипт, например,envsubst:

#!/usr/bin/env php
<?php

echo preg_replace_callback(
    '/\$(?<name>[a-z0-9_]+)/i',
    function ($matches) {
        return getenv($matches['name']);
    },
    file_get_contents('php://stdin')
);

Использование будет:

envsubst < input.file > output.file
0
20.08.2021, 12:03

Теги

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