Как обновить значение переменной из цикла A в другой цикл B — в bash

#linux #bash #loops #infinite-loop #updating

#linux #bash #циклы #бесконечный цикл #обновление

Вопрос:

Я увеличиваю значение переменной в первом цикле и использую ее во втором цикле.

Моя проблема: переменная не изменяется во втором цикле. (Это пример, я знаю, что могу переместить код, который изменяет значение, из цикла в функцию, но у меня есть программа с несколькими функциями и несколькими циклами).

Мой вопрос: как обновить значение переменной (увеличивающееся внутри первого цикла while) во втором цикле while?

Вот иллюстрация (первый цикл увеличивает значение counter_value, но второй цикл остается равным «1») :

 #!/bin/bash

counter_value="1"

function Print_counter_value () {
    echo $counter_value ; }

#_____FIRST LOOP_____
while : ; do # infinite loop
      #echo first loop works
      counter_value=$[$counter_value 1]
      echo $counter_value 1st_loop amp; sleep 2
done amp;

#_____SECOND LOOP_____
while : ; do # infinite loop
      #echo second loop works
      Print_counter_value amp; sleep 1
done amp;
  

Спасибо!

Комментарии:

1. Переместить код, который изменяет значение, из цикла в функцию?

2. @choroba Спасибо за ваш ответ, но это пример. На самом деле у меня есть несколько циклов, вызывающих одну и ту же переменную, поэтому для меня лучше обновлять переменную в каждом цикле, чем перемещать код 50 раз.

3. Процессы Bash не используют и не могут совместно использовать переменные. Вам пришлось бы записать значение в файл / канал / fifo или что-то в этом роде

Ответ №1:

Строка, которая увеличивает переменную:

 ((counter_value  ))
  

Нет необходимости переводить второй цикл в фоновый режим. Сохранение переменной в файл немного неуклюже, но это работает.

 #!/bin/bash

counter_value=1
file="/tmp/temp$$"
echo "counter_value=$counter_value" > "$file"

function Print_counter_value () {
    echo $counter_value ; }

#_____FIRST LOOP_____
while : ; do # infinite loop
    . "$file"
    ((counter_value  ))
    echo "counter_value=$counter_value" > "$file"
    sleep 2
done amp;

#_____SECOND LOOP_____
while : ; do # infinite loop
    . "$file"
    Print_counter_value amp; sleep 1
done
  

Комментарии:

1. Спасибо вам за ответ. Не могли бы вы, пожалуйста, объяснить немного больше? Я заменил строку, содержащую counter_value=$[$counter_value 1], на ((counter_value ), но это не работает.

2. Вторые циклы по-прежнему придерживаются значения 1

Ответ №2:

Вы не можете сделать это с переменными.

Используя amp; знак в конце каждого цикла, вы разветвляете процесс, то есть создаете новый процесс, который будет запускать код цикла. Каждый из этих двух новых процессов будет иметь свои собственные адресные пространства ==> counter_value отличается от адресного пространства в родительском процессе. Запись в него не изменит его значение ни в родительском процессе, ни в дочернем процессе. Будет обновлено только локальное значение.

«Я знаю, что могу переместить код, который изменяет значение, из цикла в функцию»

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

Чтобы увидеть / «поверить», что это другой процесс, вы можете напечатать внутри циклов переменные $$ (PID) и $BASHPID (PID дочернего процесса или вложенной оболочки). Вы заметите, что они отличаются друг от друга.

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