#bash #sed #environment-variables #parameter-expansion
Вопрос:
У меня есть следующий код в моем скрипте docker-entrypoint:
if [[ -v SERVICE_NAMES ]]; then
sudo sed -i -e "s#%SERVICE_NAMES%#$SERVICE_NAMES#g" /etc/someservice/someconfig.file
else
echo "SERVICE_NAMES variable not set, unable to write config without"
exit 1
fi
Содержимое переменной «SERVICE_NAMES» выглядит следующим образом при запуске контейнера:
hostname1,hostname2,hostname3
С помощью моей команды sed я хочу заменить переменную SERVICE_NAMES заполнителем в файле someconfig., но разделенным пробелом, а не запятой, чтобы ИМЕНА СЛУЖБ выглядели так в моем файле someconfig.:
hostname1 hostname2 hostname3
Можно ли заменить запятые пробелами перед записью в файл?
Ответ №1:
Использование tr
для транслитерации запятых в пробелы
tr
Команду можно использовать для транслитерации строки (заменить символ в строке другим символом). Формат выглядит следующим образом:
tr <character> <replacement-character>
tr
получает входные данные из stdin (файловый дескриптор 0
или /dev/stdin
), поэтому нам нужно либо создать конвейер Bash, либо использовать перенаправление ввода с заменой процесса, либо использовать строку здесь.
# Pipeline
echo "$SERVICE_NAMES" | tr ',' ' '
# Input Redirection with Process Substitution
tr ',' ' ' <<(echo "$SERVICE_NAMES")
# Here-String
tr ',' ' ' <<<"$SERVICE_NAMES"
Использование расширения параметров Bash для расширения запятых до пробелов
В Bash расширение параметров может использоваться для замены всех запятых пробелами. Синтаксис выглядит следующим образом: ${parameter/pattern/string}
. Однако вам необходимо убедиться, что ваш шаблон начинается с другой прямой косой черты в соответствии с справочными страницами.
Если
pattern
начинается с»/’, все совпаденияpattern
заменяются наstring
. Обычно заменяется только первый матч.
echo "${SERVICE_NAMES//,/ }"
Больше sed
команд
Команда sed
может выполнять несколько команд подряд, добавляя больше -e <command>
аргументов или разделяя команды точкой с ;
запятой, однако любые добавленные команды будут применены ко всему файлу.
Чтобы избежать влияния на весь файл, мы можем сделать отдельный вызов sed
с $SERVICE_NAMES
данными для работы. Мы можем использовать команду sed
» s y
» для выполнения транслитерации $SERVICE_NAMES
.
# Pipeline
echo "$SERVICE_NAMES" | sed -e 'y/,/ /'
# Input Redirection with Process Substitution
sed -e 'y/,/ /' <<$(echo "$SERVICE_NAMES")
# Here-String
sed -e 'y/,/ /' <<<"$SERVICE_NAMES"
Использование других языков сценариев
Я не буду приводить здесь примеры для других языков сценариев, так как их просто слишком много. В целом, большинство языков сценариев поддерживают разделение строк, объединение строк, регулярные выражения, подстановки строк/символов. Некоторые примеры этих языков-Python, JavaScript, AWK и Perl.
Для решения подобных проблем со сценариями вы можете взять свои данные и либо поместить их непосредственно в сценарий, который будет выполняться, передать данные на стандартный ввод (конвейеры, перенаправление ввода или строки здесь), либо использовать аргументы командной строки.
Ответ №2:
Вы можете использовать расширение параметра, чтобы заменить каждую запятую пробелом во время расширения переменной:
sudo sed -i -e "s#%SERVICE_NAMES%#${SERVICE_NAMES//,/ }#g" /etc/someservice/someconfig.file
Это не более рискованно, чем то, с чего вы начали, поскольку в тексте замены нет никаких дополнительных #
символов; просто имейте в виду, что если в каком-либо из ваших имен хостов появятся #
символы, sed
команда завершится ошибкой.