-1

Следующий код представляет собой упрощенную версию реальной задачи. Конечно, я знаю, что смог бы добиться того, что сделано в этом упрощенном примере, с помощью if [ ... ] . Это только для демонстрации удивительного поведения:

# /bin/bash
CURRD=dir1
IS_THIS=N
DATALINES=dir1
echo $DATALINES | while read DLINE
do
    echo IS_THIS1 ${IS_THIS}
    if [ "$DLINE" != "$CURRD" ]
    then
        echo $DLINE is not current dir
    else
        echo $DLINE is current dir
        IS_THIS=Y
        echo IS_THIS2 ${IS_THIS}
    fi
done
echo IS_THIS3 ${IS_THIS}

Я ожидаю получить этот вывод:

IS_THIS1 N
dir1 is current dir
IS_THIS2 Y
IS_THIS3 Y

Вместо этого я получаю это:

IS_THIS1 N
dir1 is current dir
IS_THIS2 Y
IS_THIS3 N

Таким образом, внутри цикла переменная IS_THIS была установлена в Y Я ожидал, что это держит это значение за пределами цикла. Но это явно не тот случай. Это возвращается к ценности, которую это имело снаружи. Это как если бы код внутри while цикла был пространством с локальными переменными. Что я не понял о скриптах оболочки bash здесь?

Я попробовал это в bash 3.2.51(1) и bash 4.1.11(2). Оба показывают одинаковое поведение.

PS: Поскольку я не мог решить реальную задачу с помощью цикла while read , я разделил входные данные при установке новой строки IFS на новую строку и инициализировал переменную массива с помощью ввода в скобках, а затем выполнил цикл for над элементами переменная массива. Так что задача решена, мне просто интересно узнать, что насчет цикла while read в bash-скриптинге я не правильно понял.

2 ответа2

1

Циклы запускаются как отдельный процесс, поэтому переменные внутри цикла уничтожаются по окончании цикла.

Если вы можете использовать Python, он сохраняет переменные внутри циклов.

currd = ["dir1"]
is_this = "n"
datalines = ["dir1"]

print is_this # checking variable

for lines in datalines:
    if lines != "".join(currd):
        print lines + " is not current dir"
    else:
        print lines + " is current dir"
        is_this = "y"

print is_this # checking if variable changed
0

Этот ответ, данный в комментарии выше l0b0, является правильным. Я бы пометил его как правильный ответ, но это комментарий, поэтому я не могу:

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

Там даны два решения. У меня на самом деле работал только один с Here-document. Для облегчения поиска ответа ниже приведен пример кода, приведенный выше с документом Here, как предлагается в USE. Он избегает конвейера и, следовательно, под-оболочки для цикла, поэтому переменная IS_THIS одинакова, и установка значения сохраняется:

# /bin/bash
CURRD=dir1
IS_THIS=N
DATALINES=dir1
while read DLINE
do
    echo IS_THIS1 ${IS_THIS}
    if [ "$DLINE" != "$CURRD" ]
    then
        echo $DLINE is not current dir
    else
        echo $DLINE is current dir
        IS_THIS=Y
        echo IS_THIS2 ${IS_THIS}
    fi
done <<< "$DATALINES"
echo IS_THIS3 ${IS_THIS}

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .