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

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

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

Настройка: я создал переменную в моем файле .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 на самом лучшем уровне, но он хотел посмотреть, не видит ли кто-нибудь риск в этом использовании?

  • Создание текстового файла из других текстовых файлов
  • Проверить количество слов в файле, содержащем конкретную букву
  • Как проверить, присутствует ли какой-либо IP-адрес в файле с использованием сценариев оболочки?
  • Получать файлы с сервера SFTP и управлять ими в памяти
  • «Stdin: не является tty» почтой для запуска скриптов в качестве заданий cron
  • Как stdin обрабатывается в этом сценарии bash?
  • Использование веб-браузера для создания галереи / слайд-шоу из локальных файлов
  • Передавать две (трубчатые) команды оболочки в качестве параметра функции оболочки
  • 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 которая поддерживает экспорт массивов изначально (используя собственную кодировку).

    Interesting Posts

    Имеет ли значение изменение пакетов через Apper или Software Center в Debian?

    Исправить плохую геометрию EXT4-fs (количество блоков превышает размер устройства)

    Команда Killall?

    Сценарий для изменения текущего каталога (cd, pwd)

    Нет звука при использовании Google Chrome

    Сценарий оболочки для проверки наличия специальных символов и блокировки специальных файлов

    Linux RDP с аудио и микрофоном

    Как использовать xpra как xvfb-run?

    Случайно выталкиваемая SD-карта физически, в то время как dd

    Как можно упростить настройки макета xkb?

    Жесткий диск USB3 не распознан Linux

    Используйте `less` для просмотра данных с запятыми

    Сон до следующего появления определенного времени

    Почему я не могу использовать `kill $!` С расширением параметра в Bash, когда самый последний процесс «уведомлять-отправлять»?

    Установка переменных в / etc / environment, не имеющих влияния, но установка их в командной строке

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