Как заменить строку переменной, разделенную запятыми, пробелами?

#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 команда завершится ошибкой.