Как сделать так, чтобы переменная была одна и та же во всём скрипте?

На самом деле это единственный раздел про unix на этом форуме

Модератор: /dev/random

Аватара пользователя
жучара
Сообщения: 305
ОС: астралинукс

Как сделать так, чтобы переменная была одна и та же во всём скрипте?

Сообщение жучара » 30.11.2019 22:28

Друзья! Требуется, чтобы переменная my_max была одна и та же во всём скрипте, а значение её пусть меняется

Код: Выделить всё

#!/bin/sh

#Вот эта переменная пусть будет одна и та же для всего скрипта
my_max=2

#Вот я её даже экспортирую
export my_max
echo $my_max 

find | while read LINE
do 
	#Изменяю её значение
	my_max=3
	echo $my_max
	exit
done

#А на самом деле оно неизменно, как было 2, так и осталось!
echo $my_max 
exit

Shell

user@astra:~$ ./foo.sh
2
3
2
user@astra:~$
Код вырожденный. В реальном коде в цикле обрабатывается вывод команды find. Тут дело в том, что из-за команды find запускается ещё один интерпретатор bash и переменная my_max, которая внутри цикла, совсем не та, что снаружи, ибо два интерпретатора- две разных переменных.

Ага, а разве export my_max не решает? Везде пишут:
export - это одна из встроенных команд оболочки пользователя bash, и предназначена для экспорта переменных и функций текущего процесса в дочерний процесс.
Так себе экспорт, сказать прямо. Не воодушевляет даже:

Код: Выделить всё

#!/bin/sh

#Вот эта переменная пусть будет одна и та же для всего скрипта
my_max=2

#Вот я её даже экспортирую
export my_max
echo $my_max 

find | while read LINE
do 
	#Изменяю её значение
	echo $my_max
	my_max=3
	echo $my_max
	exit
done

#А на самом деле оно неизменно, как было 2, так и осталось!
echo $my_max 
exit

Shell

user@astra:~$ ./foo.sh
2
2
3
2
user@astra:~$
Ну, допустим, экспортировал я переменную в дочерний процесс. А обратно, в родительский как? В общем, грустно это всё. Спасибо, кто откликнется.
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 4923
ОС: Gentoo

Re: Как сделать так, чтобы переменная была одна и та же во всём скрипте?

Сообщение /dev/random » 30.11.2019 22:35

Из дочернего процесса в родительский передавать данные можно только через внешние объекты, такие как пайпы или файлы. Настоятельно рекомендую переписать код так, чтобы модифицирующий переменные блок был в основном шелле, а не сабшелле.
Спасибо сказали:

Аватара пользователя
жучара
Сообщения: 305
ОС: астралинукс

Re: Как сделать так, чтобы переменная была одна и та же во всём скрипте?

Сообщение жучара » 30.11.2019 22:46

/dev/random, я не знаю, как грамотно сделать.

Код: Выделить всё

find > tmp
while read LINE
do 
	#Изменяю её значение
	echo $my_max
	my_max=3
	echo $my_max
	#exit
done < tmp
так опять без дополнительного файла не обойтись.
Спасибо сказали:

Аватара пользователя
/dev/random
Администратор
Сообщения: 4923
ОС: Gentoo

Re: Как сделать так, чтобы переменная была одна и та же во всём скрипте?

Сообщение /dev/random » 30.11.2019 23:01

Если у вас bash, то можно так:

Код: Выделить всё

while read LINE
do
  ...
done < <(find)
P.s. И учтите, что построчное чтение неправильно сработает на файлах с переводом строки в имени. Используйте \0 в качестве разделителя. Соответствующие опции есть и у read, и у find, но в стандарт они не входят. Это значит, что потребуются bash и gnu find.
Спасибо сказали:

Аватара пользователя
olecya
Сообщения: 37
ОС: debian, fedora (i3-wm)

Re: Как сделать так, чтобы переменная была одна и та же во всём скрипте?

Сообщение olecya » 01.12.2019 14:32

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

Код: Выделить всё

shopt -s lastpipe
или поместить команду в скобки

Код: Выделить всё

find | (your command \
else command)
Добавлено (15:00):

Код: Выделить всё

#!/bin/bash
my_max=2

shopt -s lastpipe

find | while read LINE
do 
        my_max=3
        break
done

echo $my_max
3

#!/bin/bash
my_max=2

find | (while read LINE
do 
        my_max=3
        break
done

echo $my_max)
3
Добавлено (15:13):
Если вы заметили команда exit у вас завершает работу подоболочки и не влияет на работу программы в целом.
Когда же устанавливаем опцию lastpipe команда exit будет завершать работу самого скрипта, поэтому заменяем ее на break
Спасибо сказали: