Привет, ребята. В настоящее время я пытаюсь внедрить индикатор прогресса zenity в цикл while, однако я заметил, что моя переменная, которая должна быть увеличена, не увеличилась. Вот пример тестового сценария, который я попробовал:
i=0
p=0
while [ $i -lt 10 ]
do
i=$[$i + 1]
echo $i
p=$[$p + 1]
done | (zenity --progress --title="test" --text="test")
echo "i: $i p: $p"
Я заметил, что индикатор выполнения работал, однако переменная p
, которая должна быть счетчиком, была подвержена влиянию zenity. Что-то не так с моим кодом? переменная i
предназначена для отображения значения для перемещения индикатора выполнения, а переменная p
предназначена для других целей. Значения p
и i
оба равны 0
, несмотря на увеличение его в цикле while.
Я надеюсь, что есть способ увеличить переменные p
и i
, не удаляя индикатор прогресса zenity. Однако я не уверен, почему приращение переменных работает после удаления строки (zenity --progress --title="test" --text="test")
Добавление
Как использовать переменные i
и p
после того, как индикатор выполнения закончился? И еще один вопрос, нужно ли заключать цикл while в ()
?
Спасибо за любую помощь!
zenity
. Это причина, по которой вы не получаете изменения, когда вы echo
их не используете. Я использую ваш скрипт, только добавляю что-то для печати переменных внутри цикла do while
во всплывающем окне zenity
. Чтобы узнать больше о синтаксисе диалога прогресса zenity, см. Страницу помощи gnome . Запустите приведенный ниже скрипт и посмотрите результат:
#!/bin/bash
i=0
p=0
(while [ $i -lt 100 ]
do
i=$[$i + 10]
echo $i ; sleep 1
echo "# now i is $i and p=$p"
p=$[$p + 1]
done) | zenity --progress --title="test" --text="test"
echo "i: $i p: $p"
Я изменил приращение с i
на 10, так как i
будет использоваться для приращения индикатора выполнения и используется sleep 1
для достижения прогресса Заметное.
Наблюдение: Хотя это значение увеличивается на всплывающем окне zenity
. Он показывает, что он не меняется на терминале, i: 0 p: 0
Надеюсь, это будет полезно.
Как использовать переменные подоболочки за пределами
Родительская оболочка не может использовать переменные из своей подоболочки. Вы можете найти больше о подоболочке здесь . Но вы всегда можете записать переменные из subshell во временный файл для чтения его родителем. Это может быть не лучшим из способов, но это работает.
#!/bin/bash
..
(while [ $i -lt 100 ]
do
...
...
done
echo "p=$(echo $p)" > tmp
echo "i=$(echo $i)" >> tmp
) | zenity --progress --title="test" --text="test"
. tmp
rm tmp
echo "i: $i p: $p"
Теперь он будет отображаться в терминале, как, i: 100 p: 10
, поэтому вы можете использовать их по своему желанию. И, как вы спросили в прошлой части, это не цикл while, а скорее подоболочка. Обычно в скобках помещается содержимое subshell.
Подстановка процессов может помешать созданию надоедливых субоболочек, но синтаксис немного странный:
$ k=0; for x in a b; do ((k++)); done | zenity --progress; echo "$k"
→ 0 (не в порядке)
$ k=0; for x in a b; do ((k++)); done > >(zenity --progress); echo "$k"
→ 2 (в порядке)
Что мне нравится в этом, так это то, что вам обычно не нужно сильно модифицировать свой скрипт, чтобы он работал правильно. Однако в некоторых экзотических снарядах эта функция может отсутствовать. Для Bash, проверьте раздел «Замена процесса» в руководстве.
С кодом, более близким к примеру из исходного вопроса:
i=0
p=0
while [ $i -lt 10 ]
do
i=$[$i + 1]
echo $((10 * i))
sleep 0.1
p=$[$p + 1]
done > >(zenity --progress --title="test" --text="test")
echo "i: $i p: $p"
(я добавил сон, чтобы сделать прогресс более заметным, и я повторил десять раз i
, чтобы получить 100
] при достижении конца цикла.)