Подтвердить что ты не робот

Установите родительскую переменную оболочки из подоболочки

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

a=3
(a=4)
echo $a
4b9b3361

Ответ 1

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

Вам нужна подоболочка? Если вам просто нужна группа, то используйте фигурные скобки:

a=3
{ a=4;}
echo $a

дает 4 (будьте осторожны с пространствами в этом). В качестве альтернативы напишите значение переменной stdout и запишите ее в вызывающем:

a=3
a=$(a=4;echo $a)
echo $a

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

Ответ 2

Существует gdb- bash -variable hack:

gdb --batch-silent -ex "attach $$" -ex 'set bind_variable("a", "4", 0)'; 

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

Ответ 3

Нет. У подоболочки нет доступа к родительской среде. (По крайней мере, в пределах абстракции, предоставляемой Bash. Вы могли бы попытаться использовать gdb или разбить стек или еще что-то, чтобы получить такой доступ подпольно. Однако я бы не рекомендовал это.)

Один из вариантов заключается в том, что субголда записывает операторы присваивания во временный файл для его родительского элемента:

a=3
(echo 'a=4' > tmp)
. tmp
rm tmp
echo "$a"

Ответ 4

Если проблема связана с циклом while, один из способов исправить это - с помощью замены процесса:

    var=0
    while read i;
    do
      # perform computations on $i
      ((var++))
    done < <(find . -type f -name "*.bin" -maxdepth 1)

как показано ниже: fooobar.com/questions/237461/...

Ответ 5

Чтобы изменить переменные в script, вызванные из родительского script, вы можете вызвать script, которому предшествует "."

a=3
echo $a    
. ./calledScript.sh
echo $a

в callScript.sh

a=4

Ожидаемый результат

3
4

Ответ 6

Вы можете вывести значение в подоболочке и назначить вывод подэлемента переменной в вызывающем script:

# subshell.sh
echo Value

# caller
myvar=$(subshell.sh)

Если подоболочка имеет больше выходных данных, вы можете разделить значение переменной и другие сообщения, перенаправив их в разные выходные потоки:

# subshell.sh
echo "Writing value" 1>&2
echo Value

# caller
myvar=$(subshell.sh 2>/dev/null) # or to somewhere else
echo $myvar

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

# subshell.sh
echo "a=4"

# caller
# export $(subshell.sh) would be more secure, since export accepts name=value only.
eval $(subshell.sh)
echo $a

Последнее, что я могу придумать, это использовать коды выхода, но это охватывает только обмен целыми значениями (и в ограниченном диапазоне) и нарушает соглашение для интерпретации кодов выхода (0 для успеха не-0 для всего остального).

Ответ 7

Если вы не можете применить все операции ввода-вывода к каналам и использовать файловые дескрипторы, обновление базовой переменной невозможно в $ (команда) и любом другом подпроцессе.

Обычные файлы, однако, являются глобальными переменными bash для обычной последовательной обработки. Примечание. Из-за условий гонки этот простой подход не подходит для параллельной обработки.

Создайте функцию set/get/default следующим образом:

globalVariable() { # NEW-VALUE
    # set/get/default globalVariable
    if [ 0 = "$#" ]; then
        # new value not given -- echo the value
        [ -e "$aRam/globalVariable" ] \
            && cat "$aRam/globalVariable" \
            || printf "default-value-here"
    else
        # new value given -- set the value
        printf "%s" "$1" > "$aRam/globalVariable"
    fi
}

"$ aRam" - это каталог, в котором хранятся значения. Мне нравится, что это диск памяти для скорости и волатильности:

aRam="$(mktemp -td $(basename "$0").XXX)" # temporary directory
mount -t tmpfs ramdisk "$aRam" # mount the ram disk there
trap "umount "$aRam" && rm -rf "$aRam"" EXIT # auto-eject

Чтобы прочитать значение:

v="$(globalVariable)" # or part of any command

Чтобы установить значение:

globalVariable newValue # newValue will be written to file

Чтобы сбросить значение:

rm -f "$aRam/globalVariable"

Единственная реальная причина для функции доступа - применить значение по умолчанию, потому что cat выдаст ошибку из-за несуществующего файла. Также полезно применять другую логику get/set. В противном случае, это не будет нужно вообще.

Уродливый метод чтения, позволяющий избежать несуществующей ошибки в файле cat:

v="$(cat "$aRam/globalVariable 2>/dev/null")"

Отличная особенность этого беспорядка в том, что вы можете открыть другой терминал и проверить содержимое файлов во время работы программы.