Не удается получить переменные среды массива с помощью `os.environ` [duplicate]

Используйте $(parent).html(code) вместо parent.innerHTML = code.

Ниже также исправлены скрипты, использующие document.write и скрипты, загруженные через атрибут src. К сожалению, даже это не работает с скриптами Google AdSense.

var oldDocumentWrite = document.write;
var oldDocumentWriteln = document.writeln;
try {
    document.write = function(code) {
        $(parent).append(code);
    }
    document.writeln = function(code) {
        document.write(code + "
"); } $(parent).html(html); } finally { $(window).load(function() { document.write = oldDocumentWrite document.writeln = oldDocumentWriteln }) }

Источник

41
задан Remiii 6 April 2011 в 10:53
поделиться

9 ответов

Невозможно экспортировать (пока) переменные массива.

Из manpage версии bash 4.1.5 в разделе ubuntu 10.04.

Следующее утверждение из Chet Ramey (текущий разработчик bash по состоянию на 2011 год), вероятно, является самой официальной документацией об этой «ошибке»:

На самом деле нет хорошего способа кодирования переменной массива в среде.

http://www.mail-archive.com/bug-bash@gnu.org/msg01774.html

39
ответ дан lesmana 19 August 2018 в 03:58
поделиться
  • 1
    странно, ссылка bash не упоминает об этом – Eugene Yarmash 6 April 2011 в 11:15
  • 2
    Ugh ... Для всех вещей bash он не может экспортировать массив для использования других скриптов ... – jww 25 October 2017 в 04:07
  • 3
    Вы не можете экспортировать массив по той же причине, в какой вам нужны массивы: вы не можете безопасно сгладить массив в одну строку с нулевым разделителем без потери структуры массива. – chepner 1 June 2018 в 20:25

вы (hi!) можете использовать это, не нужно писать файл, для ubuntu 12.04, bash 4.2.24

Кроме того, ваш массив с несколькими строками может быть экспортирован.

cat >> exportArray.sh

function FUNCarrayRestore() {
    local l_arrayName=$1
    local l_exportedArrayName=${l_arrayName}_exportedArray

    # if set, recover its value to array
    if eval '[[ -n ${'$l_exportedArrayName'+dummy} ]]'; then
        eval $l_arrayName'='`eval 'echo $'$l_exportedArrayName` #do not put export here!
    fi
}
export -f FUNCarrayRestore

function FUNCarrayFakeExport() {
    local l_arrayName=$1
    local l_exportedArrayName=${l_arrayName}_exportedArray

    # prepare to be shown with export -p
    eval 'export '$l_arrayName
    # collect exportable array in string mode
    local l_export=`export -p \
        |grep "^declare -ax $l_arrayName=" \
        |sed 's"^declare -ax '$l_arrayName'"export '$l_exportedArrayName'"'`
    # creates exportable non array variable (at child shell)
    eval "$l_export"
}
export -f FUNCarrayFakeExport

проверить этот пример на терминальном bash (работает с bash 4.2.24):

source exportArray.sh
list=(a b c)
FUNCarrayFakeExport list
bash
echo ${list[@]} #empty :(
FUNCarrayRestore list
echo ${list[@]} #profit! :D

Я могу улучшить его здесь

PS .: Если кто-то очищает / улучшает / makeItRunFaster, я хотел бы знать / see, thx! : D

0
ответ дан Aquarius Power 19 August 2018 в 03:58
поделиться

Я редактировал другую запись и сделал ошибку. Augh. В любом случае, возможно, это может помочь? https://stackoverflow.com/a/11944320/1594168

Обратите внимание, что поскольку формат массива оболочки недокументирован в bash или любой другой стороне оболочки, очень трудно вернуться массив оболочек независимо от платформы. Вам нужно будет проверить версию, а также создать простой скрипт, который объединяет все массивы оболочек в файл, который могут разрешить другие процессы.

Однако, если вы знаете имя массива, который хотите принять назад домой, тогда есть способ, хотя немного грязный.

Допустим, у меня есть

MyAry[42]="whatever-stuff";
MyAry[55]="foo";
MyAry[99]="bar";

Итак, я хочу забрать его домой

name_of_child=MyAry
take_me_home="`declare -p ${name_of_child}`";
export take_me_home="${take_me_home/#declare -a ${name_of_child}=/}"

Мы можем видеть, что он экспортируется путем проверки из подпроцесса

echo ""|awk '{print "from awk =["ENVIRON["take_me_home"]"]";  }'

Результат:

from awk =['([42]="whatever-stuff" [55]="foo" [99]="bar")']

Если мы абсолютно обязаны, используйте env var для его выгрузки.

env > some_tmp_file

Затем

Перед запуском другого скрипта,

# This is the magic that does it all
source some_tmp_file
0
ответ дан Community 19 August 2018 в 03:58
поделиться

Для массивов со значениями без пробелов я использовал простой набор функций для итерации по каждому элементу массива и конкатенации массива:

_arrayToStr(){
    array=($@)

    arrayString=""
    for (( i=0; i<${#array[@]}; i++ )); do
        if [[ $i == 0 ]]; then
            arrayString="\"${array[i]}\""
        else
            arrayString="${arrayString} \"${array[i]}\""
        fi
    done

    export arrayString="(${arrayString})"
}

_strToArray(){
    str=$1

    array=${str//\"/}
    array=(${array//[()]/""})

    export array=${array[@]}
}

Первая функция с превращением массива в string, добавляя открывающиеся и закрывающиеся круглые скобки и избегая всех двойных кавычек. Вторая функция разделит кавычки и скобки и поместит их в фиктивный массив.

Чтобы экспортировать массив, вы должны передать все элементы исходного массива:

array=(foo bar)
_arrayToStr ${array[@]}

На этом этапе массив был экспортирован в значение $ arrayString. Чтобы импортировать массив в файл назначения, переименуйте массив и выполните противоположное преобразование:

_strToArray "$arrayName"
newArray=(${array[@]})
0
ответ дан markantonio37 19 August 2018 в 03:58
поделиться

Jeez. Я не знаю, почему другие ответы сделали это настолько сложным. Bash имеет почти встроенную поддержку для этого.

В сценарии экспорта:

myArray=( '  foo"bar  ' $'\n''\nbaz)' )  # an array with two nasty elements

myArray="${myArray[@]@Q}" ./importing_script.sh

(обратите внимание, двойные кавычки необходимы для правильной обработки пробелов в элементах массива.)

При входе в importing_script.sh значение переменной среды myArray содержит эти точные 26 байтов:

'  foo"bar  ' $'\n\\nbaz)'

Затем восстанавливается следующий массив:

eval "myArray=( ${myArray} )"

ВНИМАНИЕ! Не нравится eval, если вы не можете доверять источнику переменной среды myArray. Этот трюк демонстрирует уязвимость «Маленькие бреющие столы» . Представьте, чтобы кто-то установил значение myArray на ) ; rm -rf / #.

1
ответ дан Matt Whitlock 19 August 2018 в 03:58
поделиться
  • 1
    Я думал, что eval является опасной функцией, и ее нельзя использовать в сценариях. – jww 25 October 2017 в 04:08
  • 2
    @jww: eval is опасно, если вы не можете быть уверены в содержании проверяемой строки. Прочтите мое ПРЕДОСТЕРЕЖЕНИЕ выше. – Matt Whitlock 26 October 2017 в 12:47
  • 3
    Хорошо, это приведет к удалению функциональности массива. Простейшим рабочим решением является не запуск новой оболочки, а выполнение сценария в контексте текущей оболочки: stackoverflow.com/questions/8352851/… с использованием source othershellscript – dothebart 1 December 2017 в 15:40
  • 4
    @dothebart: Что вы подразумеваете под «удалением функциональности массива» ?? Следуя моему предложению, переменная оболочки myArray в дочернем процессе будет содержать массив, эквивалентный массиву, содержащемуся в переменной оболочки myArray в родительском процессе. (Возможно, вы упустили круглые скобки в заявлении eval?) – Matt Whitlock 8 December 2017 в 06:17
  • 5
    Ах, извините @MattWhitlock, я пропустил часть eval - мой плохой. – dothebart 8 December 2017 в 16:17
25
ответ дан mr.spuratic 19 August 2018 в 03:58
поделиться

Основываясь на использовании @mr.spuratic BASH_ENV, здесь I туннель $@ через script -f -c

script -c <command> <logfile> можно использовать для запуска команды внутри другой pty (и группы процессов) но он не может передать какие-либо структурированные аргументы в <command>.

Вместо <command> является простой строкой, которая будет аргументом для вызова библиотеки system.

Мне нужно туннель $@ внешнего bash в $@ of bash, вызванный скриптом.

Поскольку declare -p не может принимать @, здесь я использую магическую переменную bash _ (с фиктивным значением первого массива, которое будет перезаписано bash). Это спасает меня от любых важных переменных:

Доказательство концепции: BASH_ENV=<( declare -a _=("" "$@") && declare -p _ ) bash -c 'set -- "${_[@]:1}" && echo "$@"'

«Но, вы говорите,« вы передаете аргументы в bash - и действительно я , но это простая строка известного символа. Здесь используется script

SHELL=/bin/bash BASH_ENV=<( declare -a _=("" "$@") && declare -p _ && echo 'set -- "${_[@]:1}"') script -f -c 'echo "$@"' /tmp/logfile

, которая дает мне эту функцию-обертку in_pty:

in_pty() { SHELL=/bin/bash BASH_ENV=<( declare -a _=("" "$@") && declare -p _ && echo 'set -- "${_[@]:1}"') script -f -c 'echo "$@"' /tmp/logfile }

или эта обертка без функции в качестве составной строки для Makefiles:

in_pty=bash -c 'SHELL=/bin/bash BASH_ENV=<( declare -a _=("" "$$@") && declare -p _ && echo '"'"'set -- "$${_[@]:1}"'"'"') script -qfc '"'"'"$$@"'"'"' /tmp/logfile' --

...

$(in_pty) test --verbose $@ $^

0
ответ дан Sam Liddicott 19 August 2018 в 03:58
поделиться

Как сообщалось Lesmana, вы не можете экспортировать массивы. Поэтому вы должны их сериализовать, прежде чем проходить через среду. Эта сериализация полезно для других мест, где подходит только строка (su -c 'string', ssh host 'string'). Самый короткий способ сделать это - злоупотреблять «getopt»

# preserve_array(arguments). return in _RET a string that can be expanded
# later to recreate positional arguments. They can be restored with:
#   eval set -- "$_RET"
preserve_array() {
    _RET=$(getopt --shell sh --options "" -- -- "$@") && _RET=${_RET# --}
}

# restore_array(name, payload)
restore_array() {
   local name="$1" payload="$2"
   eval set -- "$payload"
   eval "unset $name && $name=("\$@")"
}

Использовать его следующим образом:

foo=("1: &&& - *" "2: two" "3: %# abc" )
preserve_array "${foo[@]}"
foo_stuffed=${_RET}
restore_array newfoo "$foo_stuffed"
for elem in "${newfoo[@]}"; do echo "$elem"; done

## output:
# 1: &&& - *
# 2: two
# 3: %# abc

Это не относится к unset / разреженным массивам. Возможно, вы сможете уменьшить 2 'eval' вызовы в файле restore_array.

1
ответ дан smoser 19 August 2018 в 03:58
поделиться
0
ответ дан Sam Liddicott 30 October 2018 в 15:47
поделиться
Другие вопросы по тегам:

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