Приращение переменной в bash - PullRequest
9 голосов
/ 20 сентября 2011

Рассмотрим следующий скрипт:

#!/bin/bash

num=0
cat file | while read line; do
    echo "$line"
    lines[$num]="$line"
    ((num++))
    echo "num = $num"
done

echo "end num = $num"

i=0
while [ $i -lt $num ]; do
    echo "${lines[$i]}"
    ((i++))
done

Обычно, он должен читать файл построчно, сохранять результат в массиве, затем проходить через массив и печатать его построчно. Проблема в том, что переменная $ num сбрасывается как-то после выхода из первого цикла. Вывод этого сценария для меня следующий (используется файл со случайным мусором в нем):

dsfkljhhsdfsdfshdjkfgd
num = 1
fdfgdfgdfg
num = 2
dfgdfgdfgdfg
num = 3
dfgdfgdfgdfgdfg
num = 4
dfgdfgdfgdfgdfgd
num = 5
fgdfgdfgdfg
num = 6
dfgdfgdfgdfg
num = 7
dfgdfgdfgdfgdfg
num = 8
dfgdfgdfgdfg
num = 9
dfgdfgdgdgdg
num = 10
dfgdffgdgdgdg
num = 11
end num = 0

Почему это? Как мне добиться, чтобы запомнить переменную? Я использую bash 3.1.17 в SUSE Linux 10.

Ответы [ 3 ]

15 голосов
/ 20 сентября 2011

Почему?Это происходит потому, что:

cat file | while read line; do
    echo "$line"
    lines[$num]="$line"
    ((num++))
    echo "num = $num"
done

выполняет оператор while в отдельном процессе, со своей собственной средой, не затрагивая родительскую среду.Точно так же вы обнаружите, что массива lines там тоже нет.

Следующий упрощенный скрипт показывает это в действии:

#!/bin/bash
export xyzzy=42
echo urk | while read line; do
    xyzzy=999
    echo $xyzzy
done
echo $xyzzy

Вывод этого скрипта:

999
42

, поскольку в подпроцессе задано значение переменной 999.

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

Если вы используете перенаправление ввода вместо запуска подпроцессаТрубопровод, он должен работать как хочешь.Это связано с тем, что бит while выполняется в контексте current , а не отдельного процесса в конвейере.Например:

#!/bin/bash
export xyzzy=42
while read line; do
    xyzzy=999
    echo $xyzzy
done <<EOF
hello
EOF
echo $xyzzy

произведет:

999
999

Для вашего конкретного случая замените:

done <<EOF
hello
EOF

на:

done <file
3 голосов
/ 20 сентября 2011

Чтобы добавить к предыдущему ответу: и чтобы избежать этого (и UUOC), вам понадобится что-то вроде этого:

while ...; do
  ...
done < file
0 голосов
/ 14 августа 2013

Просто держите ваши переменные в одной среде.В строке 4 удалите «cat file |».В строке 9 добавьте «<файл».Ваш конечный номер теперь будет содержать ожидаемые 11, а массив lines будет печатать по одному элементу за раз через ваш второй цикл. </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...