Work-Around для хранения значений массива в переменной среды, а затем вызов из сценария Bash

Я искал ответ на вопрос «Могу ли я использовать массив как переменную среды, а затем вызывать его из сценария оболочки Bash» и пришел к выводу, что он не был «официально» поддержан как (описанный здесь и здесь ) ,

Однако мне действительно нужно было это сделать и придумал «обход», и мне хотелось узнать ваше мнение.

  • Узнайте, где $ PATH был поврежден
  • Разбиение рабочего каталога в сценарии bash
  • Как перечислить файлы резервных копий, отсутствующие в соответствующих файлах?
  • bash молча выполняет функцию return on (re) объявляет глобальный ассоциативный массив только для чтения
  • Многострочная переменная с пробелами, добавление каждой строки в массив
  • Создание многоадресного соединения для tcpdump-захватов
  • Настройка: я создал переменную в моем файле .profile который выглядит примерно так:

     HOST_NAMES='server1 server2 server3' 

    Затем в начале моего сценария оболочки я написал:

     SRVR_ARRAY=($(echo $HOST_NAMES | awk '{for (i = 1; i <=NF; i++) print $i " "}')) 

    Позже в сценарии, когда пришло время сделать какую-то работу, я позвонил:

     for h in "${SRVR_ARRAY[@]}"; do ping $h done 

    И это сработало! Теперь я уверен, что это скрипт оболочки Bash jerry-riggin на самом лучшем уровне, но он хотел посмотреть, не видит ли кто-нибудь риск в этом использовании?

  • Как печатать номера строк с соответствующей строкой, соответствующей шаблону с помощью команды оболочки?
  • Как скрипт bash обнаруживает поддержку escape-символов титрования окна?
  • Псевдоним команды для запуска в фоновом режиме
  • Как создать список, сгенерированный md5deep в алфавитном порядке относительных путей?
  • Параметры команды загрузки из файла верхнего уровня
  • как удалить ssh предупреждение в сценарии оболочки
  • 2 Solutions collect form web for “Work-Around для хранения значений массива в переменной среды, а затем вызов из сценария Bash”

    Проблемы, с которыми вы можете столкнуться, это обычные: расщепление и глотание.

    Вы не можете иметь строки с пробелами, так как они будут разделены на отдельные элементы массива, и все, что напоминает символ glob ( *?[] ), Будет расширено до соответствия именам файлов. Вероятно, это не проблема с именами хостов, но, в общем, это так.

    Это обычная проблема, которая неоднократно обсуждалась, например, расширение расширения оболочки и влияние glob и ее разделение на нее, а также последствия для безопасности забывания при цитировании переменной в оболочках bash / POSIX


    Чтобы обойти их, вам нужно: a) установить IFS на что-то другое, кроме пробелов, и разделить ваши строки с этим, и b) отключить глобирование с помощью set -f .

    Это будет использовать | как разделитель и разделить строку. Вы можете использовать любой символ, который не нужен в значениях, возможно, даже некоторый контрольный символ, такой как \001 (используйте B $'\001' в Bash для его создания).

     #!/bin/bash string='foo|bar' IFS='|'; set -f array=($string) # split it IFS='|' string="${array[*]}" # merge it back together 

    Кроме того, как они говорят в комментариях, если ваша переменная имеет только имена хостов, и вы в порядке с разбиением на пробелы, вам не нужен awk, чтобы разбить ее. Оболочка сделает это при назначении массиву или запуске цикла:

     SRVR_ARRAY=( $HOST_NAMES ) for x in $HOST_NAMES ; do ... 

    (Опять же, вы получите проблемы, если HOST_NAMES содержит символы glob.)

    На самом деле, это будет происходить даже с вашим примером: awk что-то печатает, оболочка ловит его, разделяет его на слова, поскольку $() не находится внутри двойных кавычек, а затем сохраняет слова отдельно в массиве.

    Вместо этого вы можете сохранить результат declare -p в переменной окружения:

     array=(foo 'bar baz'); array[12]=sparse export ARRAY_definition="$(declare -p array)" 

    Затем в исполняемом сценарии bash :

     eval "$ARRAY_definition" 

    Обратите внимание, что важно, чтобы eval выполнялся в той же локали, что и declare одну (и предпочтительно такую ​​же версию bash )

    Если eval не запущен в глобальной области, массив будет объявлен локальным .

    С помощью zsh вы можете использовать цитирование, чтобы избежать необходимости использовать эту опасную eval :

     export ARRAY_definition=${(j: :)${(q)array}} 

    импортировать с помощью:

     array=(${(Q)${(z)ARRAY_definition}}) 

    В качестве альтернативы вы можете использовать оболочку типа rc , es или fish которая поддерживает экспорт массивов изначально (используя собственную кодировку).

    Linux и Unix - лучшая ОС в мире.