Пример:
-------------------------------------
#!/bin/bash
M=0
for N in 1 2 3 4 5
do
let M=$M+$N
done
echo $M # получается 0 !!!
-------------------------------------
Как я понимаю, для выполнения цикла bash запускает еще одну свою копию, копирует ей свое
окружение. А когда эта копия завешается, то переменная М не может быть передана обратно родителю и заменить собой его переменную М.
Эту проблему можно обойти записывая М каждый раз в файл, а потом, когда надо - прочитать.
Но, мне кажется, это дурной тон - писать в файл на каждой итерации цикла.
Пробовал export и declare - не помогает.Как же все-таки передать значение переменной от ребенка к родителю?
>Пример:
>-------------------------------------
>#!/bin/bash
>M=0
>for N in 1 2 3 4 5
>do
> let M=$M+$N
>done
>echo $M # получается 0 !!!
>-------------------------------------
>Как я понимаю, для выполнения цикла bash запускает еще одну свою копию,
>копирует ей свое
>окружение. А когда эта копия завешается, то переменная М не может быть
>передана обратно родителю и заменить собой его переменную М.
>Эту проблему можно обойти записывая М каждый раз в файл, а потом,
>когда надо - прочитать.
>Но, мне кажется, это дурной тон - писать в файл на каждой
>итерации цикла.
>Пробовал export и declare - не помогает.
>
>Как же все-таки передать значение переменной от ребенка к родителю?Что-то у вас не так... Вот что у меня bash выдает:
bash-2.05a$ cat test.sh
#!/usr/local/bin/bash
M=0
for N in 1 2 3 4 5
do
let M=$M+$N
done
echo $Mbash-2.05a$ ./test.sh
15А у вас какие сообщения появляются на экране?
>>Пример:
>>-------------------------------------
>>#!/bin/bash
>>M=0
>>for N in 1 2 3 4 5
>>do
>> let M=$M+$N
>>done
>>echo $M # получается 0 !!!
>>-------------------------------------
>>Как я понимаю, для выполнения цикла bash запускает еще одну свою копию,
>>копирует ей свое
>>окружение. А когда эта копия завешается, то переменная М не может быть
>>передана обратно родителю и заменить собой его переменную М.
>>Эту проблему можно обойти записывая М каждый раз в файл, а потом,
>>когда надо - прочитать.
>>Но, мне кажется, это дурной тон - писать в файл на каждой
>>итерации цикла.
>>Пробовал export и declare - не помогает.
>>
>>Как же все-таки передать значение переменной от ребенка к родителю?
>
>Что-то у вас не так... Вот что у меня bash выдает:
>
>bash-2.05a$ cat test.sh
>#!/usr/local/bin/bash
>M=0
>for N in 1 2 3 4 5
>do
>let M=$M+$N
>done
>echo $M
>
>bash-2.05a$ ./test.sh
>15
>
>А у вас какие сообщения появляются на экране?Да, вы правы. Я не прав. Приведенный мною пример неудачен. Я потом его сам набрал и
убедился, что он работает. Хотя и не понятно, почему.
Дело в том, что уже несколько лет я наступаю на эти грабли и всегда лень разобраться.
Как-нибудь обхожу эту проблему.
Попозже смогу привести реальный скрипт, где проявляется эта проблема.
Но мне кажется, что этот вопрос можно применить и к функциям.
Например. Объявляем функцию, а потом вызываем ее. Как можно получить результат ее работы?
Я знаю только три способа:
1. return 0 или 1 по условию, например.
2. PEREMENNAIA=`function abc 123`,
тогда в функции нужно сделать, что-то типа "echo 456"
3. Внутри функции "echo $XXX >> file.ext".
В основном скрипте "cat file.ext | while read ROW"
Третий способ самый удобный, когда в функции есть цикл с выводом данных, но и самый медленный и не красивый.
Идеальным вариантом было бы внутри функции устанавливать значения переменных, а в теле скрипта пользоваться ими.
>Но мне кажется, что этот вопрос можно применить и к функциям.
>Например. Объявляем функцию, а потом вызываем ее. Как можно получить результат ее
>работы?
>Я знаю только три способа:
>1. return 0 или 1 по условию, например.
>2. PEREMENNAIA=`function abc 123`,
> тогда в функции нужно сделать, что-то типа "echo 456"
>
>3. Внутри функции "echo $XXX >> file.ext".
> В основном скрипте "cat file.ext | while read ROW"
>
>Третий способ самый удобный, когда в функции есть цикл с выводом данных,
>но и самый медленный и не красивый.
>Идеальным вариантом было бы внутри функции устанавливать значения переменных, а в теле
>скрипта пользоваться ими.function result_in_var () {
var=`long-command`
}или
function result_in_stdout () {
echo "hello"
...
}result_in_stdout | while read ...
>
>function result_in_var () {
> var=`long-command`
>}
А в теле основного скрипта эта var будет пуста....>result_in_stdout | while read ...
Вот за это спасибо. Недопер, что можно вывод функции перенаправить в конвеер.
Вот кусок из конкретного скрипта подготовки данных для табеля рабочего времени.
Он построчно читает файл графика работы и преобразовывает его в три массива - начало,
конец и продолжительность рабочего дня.
Прошу не обращать внимание на бессмысленность последнего выода (3) - это только для примера.#!/bin/bash
# Create grafic.csv. Only for example script!
cat << ! > grafic.csv.example
date,date,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
user,ivanov,10:00-20:00,09:30-22:30,11:00-19:00,11:30-18:30,12:00-18:00,12:30-17:30,13:00-17:00,13:30-16:30,14:00-16:00,14:30-15:30,15:00-15:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00
user,petrov,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00
user,sidorov,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00,10:00-20:00
!exec 2>$0.err
set -xdeclare -a GRAFIC_TIMES
declare -a GRAFIC_TIMES_BEGIN
declare -a GRAFIC_TIMES_END
declare -a GRAFIC_TIMES_DELTA############################################################################
function convert-time-human-unix() # 23:59 -> 12345
{
DATE=`echo $1 | tr ':,.' ':'`
MINUTES=`echo $DATE | cut -d : -f 2`
HOUERS=`echo $DATE | cut -d : -f 1`#awk "BEGIN {print $SECONDS+$MINUTES*60+$HOUERS*3600}"
awk "BEGIN {print $MINUTES*60+$HOUERS*3600}"
}
############################################################################
function convert-time-unix-human() # 12345 -> 23:59
{
DATA=$1
let HOUERS=$DATA/3600
if [ $HOUERS -lt 10 ]
then
HOUERS=0$HOUERS
fiDATA=`awk "BEGIN {print $DATA-$HOUERS*3600}"`
let MINUTES=$DATA/60
if [ $MINUTES -lt 10 ]
then
MINUTES=0$MINUTES
fiecho "$HOUERS:$MINUTES"
}
###############################################################################
#
# BEGIN
#
GRAFIC_MONTH=05
GRAFIC_YEAR=2006###############################################################################
#For every user
grep -e "^user," grafic.csv.example |
while read ROW
doOLD_IFS=$IFS
IFS=","
set $ROW
IFS=$OLD_IFS
USERNAME=$2
shift 1
GRAFIC_TIMES=($@)
### GRAFIC_TIMES=ivanov 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00 10:00-20:00let CNT=1
while [ $CNT != ${#GRAFIC_TIMES[@]} ]
doif [ $CNT -lt 10 ]
then
DAY=0$CNT
else
DAY=$CNT
fiGRAFIC_TIME=${GRAFIC_TIMES[$CNT]}
OLD_IFS=$IFS
IFS="-"
set $GRAFIC_TIME
IFS=$OLD_IFS
GRAFIC_TIME_BEGIN=$1
GRAFIC_TIME_END=$2
GRAFIC_TIME_BEGIN_SEC=`convert-time-human-unix $GRAFIC_TIME_BEGIN`
GRAFIC_TIME_END_SEC=`convert-time-human-unix $GRAFIC_TIME_END`
let GRAFIC_TIME_DELTA_SEC=$GRAFIC_TIME_END_SEC-$GRAFIC_TIME_BEGIN_SEC
GRAFIC_TIME_DELTA=`convert-time-unix-human $GRAFIC_TIME_DELTA_SEC`GRAFIC_TIMES_BEGIN[$CNT]=$GRAFIC_TIME_BEGIN
GRAFIC_TIMES_END[$CNT]=$GRAFIC_TIME_END
GRAFIC_TIMES_DELTA[$CNT]=$GRAFIC_TIME_DELTAlet CNT=$CNT+1
echo ${GRAFIC_TIMES_BEGIN[@]} > 1.out # (1)
echo ${GRAFIC_TIMES_END[@]} >> 1.out
echo ${GRAFIC_TIMES_DELTA[@]} >> 1.out
done
echo ${GRAFIC_TIMES_BEGIN[@]} > 2.out # (2)
echo ${GRAFIC_TIMES_END[@]} >> 2.out
echo ${GRAFIC_TIMES_DELTA[@]} >> 2.out
done
echo ${GRAFIC_TIMES_BEGIN[@]} > 3.out # (3)
echo ${GRAFIC_TIMES_END[@]} >> 3.out
echo ${GRAFIC_TIMES_DELTA[@]} >> 3.outecho $SECONDS
Конец.
Так вот, вывод (1) содержит данные, (2) тоже, а вывод (3) пуст....
>>
>>function result_in_var () {
>> var=`long-command`
>>}
>А в теле основного скрипта эта var будет пуста....проверь. вот тебе рабочий пример:
function result_in_var () {
var = $1
}result_in_var 12345
echo $var
>function result_in_var () {
> var = $1
^^^^только пробелов перед и после присваивания не нужно:
var=$1