Как установить переменную в родительской оболочке из подоболочки?
a=3
(a=4)
echo $a
Как установить переменную в родительской оболочке из подоболочки?
a=3
(a=4)
echo $a
Вся точка подоболочки заключается в том, что она не влияет на вызывающий сеанс. В bash подоболочка представляет собой дочерний процесс, другие оболочки отличаются, но даже тогда параметр переменной в подоболочке не влияет на вызывающего. По определению.
Вам нужна подоболочка? Если вам просто нужна группа, то используйте фигурные скобки:
a=3
{ a=4;}
echo $a
дает 4
(будьте осторожны с пространствами в этом). В качестве альтернативы напишите значение переменной stdout и запишите ее в вызывающем:
a=3
a=$(a=4;echo $a)
echo $a
избегать использования обратных тиков ``, они устарели и могут быть трудночитаемыми.
Существует gdb- bash -variable hack:
gdb --batch-silent -ex "attach $$" -ex 'set bind_variable("a", "4", 0)';
хотя всегда задает переменную в глобальной области, а не только родительскую область
Нет. У подоболочки нет доступа к родительской среде. (По крайней мере, в пределах абстракции, предоставляемой Bash. Вы могли бы попытаться использовать gdb
или разбить стек или еще что-то, чтобы получить такой доступ подпольно. Однако я бы не рекомендовал это.)
Один из вариантов заключается в том, что субголда записывает операторы присваивания во временный файл для его родительского элемента:
a=3
(echo 'a=4' > tmp)
. tmp
rm tmp
echo "$a"
Если проблема связана с циклом while, один из способов исправить это - с помощью замены процесса:
var=0
while read i;
do
# perform computations on $i
((var++))
done < <(find . -type f -name "*.bin" -maxdepth 1)
как показано ниже: fooobar.com/questions/237461/...
Чтобы изменить переменные в script, вызванные из родительского script, вы можете вызвать script, которому предшествует "."
a=3
echo $a
. ./calledScript.sh
echo $a
в callScript.sh
a=4
Ожидаемый результат
3
4
Вы можете вывести значение в подоболочке и назначить вывод подэлемента переменной в вызывающем 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 для всего остального).
Если вы не можете применить все операции ввода-вывода к каналам и использовать файловые дескрипторы, обновление базовой переменной невозможно в $ (команда) и любом другом подпроцессе.
Обычные файлы, однако, являются глобальными переменными 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")"
Отличная особенность этого беспорядка в том, что вы можете открыть другой терминал и проверить содержимое файлов во время работы программы.