Локальные переменные после выхода из цикла

bash

9236 просмотра

5 ответа

56 Репутация автора

У меня возникли некоторые проблемы с локальными переменными после выхода из цикла. Переменная maxзаканчивается значением 0, несмотря на код ниже:

max=0
cat tmp|while read line
do
temp=$(echo $line|tr -d "\n"|wc -c)
if [ $temp -gt $max ];then

max=$temp
echo $max
fi
done
echo -n tmp $max

cat tmp
12345
123456

И это вывод, который я получаю:

5
6
 tmp 0

Я не понимаю, почему max0 после выхода из цикла, в то время как внутри цикла он находит правильные значения.

Автор: Leo Источник Размещён: 13.01.2010 08:40

Ответы (5)


13 плюса

622054 Репутация автора

Решение

Труба запускает новую подоболочку с собственным окружением и переменным пространством. Используйте < tmpвместо этого в конце цикла.

Автор: Ignacio Vazquez-Abrams Размещён: 13.01.2010 08:47

3 плюса

22949 Репутация автора

max=0
while read line
do
    temp=$(echo $line|tr -d "\n"|wc -c)
    if [ $temp -gt $max ]
    then 
        max=$temp
        echo $max
    fi
done <tmp
echo -n tmp $max
Автор: Paul Creasey Размещён: 13.01.2010 08:55

1 плюс

8062 Репутация автора

Канал перед вашим временем помещает все внутри цикла в отдельную оболочку и, таким образом, в отдельный контекст идентификатора (по сути, в новую среду).

Перенаправление tmpфайла в whileцикл с помощью <будет держать ваш цикл и переменные в одном контексте выполнения.

while read line
do
    # your loop stuff 
done < tmp
Автор: dustmachine Размещён: 13.01.2010 08:56

3 плюса

336 Репутация автора

Согласно справочной странице bash каждая команда в конвейере выполняется в подоболочке. То есть ваш цикл while выполняется в подоболочке, и изменяется только значение переменной max в этой подоболочке.

Переменные подоболочек не передаются обратно вызывающей оболочке, которая выполняет команду echo и, таким образом, все еще видит начальное нулевое значение.

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

max=0
cat tmp|{
    while read line
    do
        temp=$(echo $line|tr -d "\n"|wc -c)
        if [ $temp -gt $max ];then
            max=$temp
        fi
    done
    echo -n tmp $max
}

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

max=0
max=$(cat tmp|{
    while read line
    do
        temp=$(echo $line|tr -d "\n"|wc -c)
        if [ $temp -gt $max ];then
            max=$temp
        fi
    done
    echo -n $max
})
echo tmp $max
Автор: lwho Размещён: 13.01.2010 09:14

0 плюса

242874 Репутация автора

Вот один вкладыш в awk.

$ awk 'length>t{t=length}END{print t}' file
6
Автор: ghostdog74 Размещён: 14.01.2010 12:06
Вопросы из категории :
32x32