Bash

退出帶有嵌套循環的 shell 腳本

  • March 20, 2020

我有一個帶有嵌套循環的 shell 腳本,只是發現“exit”並沒有真正退出腳本,而只是目前循環。是否有另一種方法可以在某個錯誤條件下完全退出腳本?

我不想使用“set -e”,因為存在可接受的錯誤,並且需要進行太多重寫。

現在,我正在使用 kill 手動終止程序,但似乎應該有更好的方法來做到這一點。

您的問題本身不是嵌套循環。這是您的一個或多個內部循環在 subshel​​l 中執行

這有效:

#!/bin/bash

for i in $(seq 1 100); do
       echo i $i
       for j in $(seq 1 10) ; do
               echo j $j
               sleep 1
               [[ $j = 3 ]] && { echo "I've had enough!" 1>&2; exit 1; }
       done
       echo "After the j loop."
done
echo "After all the loops."

輸出:

i 1
j 1
j 2
j 3
I've had enough!

這提出了您描述的問題:

#!/bin/bash

for i in $(seq 1 100); do
       echo i $i
       cat /etc/passwd | while read line; do
               echo LINE $line
               sleep 1
               [[ "$line" = "daemon:x:2:2:daemon:/sbin:/sbin/nologin" ]] && { echo "I've had enough!" 1>&2; exit 1; }
       done
       echo "After the j loop."
done    
echo "After all the loops."

輸出:

i 1
LINE root:x:0:0:root:/root:/bin/bash
LINE bin:x:1:1:bin:/bin:/sbin/nologin
LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!
After the j loop.
i 2
LINE root:x:0:0:root:/root:/bin/bash
LINE bin:x:1:1:bin:/bin:/sbin/nologin
LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!
After the j loop.
i 3
LINE root:x:0:0:root:/root:/bin/bash
(...etc...)

這是解決方案;您必須測試在子外殼中執行的內部循環的返回值:

#!/bin/bash

for i in $(seq 1 100); do
       echo i $i
       cat /etc/passwd | while read line; do
               echo LINE $line
               sleep 1
               [[ "$line" = "daemon:x:2:2:daemon:/sbin:/sbin/nologin" ]] && { echo "I've had enough!" 1>&2; exit 1; }
       done
       err=$?; [[ $err != 0 ]] && exit $err
       echo "After the j loop."
done
echo "After all the loops."

注意測試:[[ $? != 0 ]] && exit $?

輸出:

i 1
LINE root:x:0:0:root:/root:/bin/bash
LINE bin:x:1:1:bin:/bin:/sbin/nologin
LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!

編輯:要驗證您所在的子外殼,請修改“答案”腳本以告訴您目前外殼的程序 ID 是什麼。注意:這僅適用於 bash 4:

#!/bin/bash

for i in $(seq 1 100); do
       echo pid $BASHPID i $i
       cat /etc/passwd | while read line; do
               echo pid $BASHPID LINE $line
               sleep 1
               [[ "$line" = "daemon:x:2:2:daemon:/sbin:/sbin/nologin" ]] && { echo "I've had enough!" 1>&2; exit 1; }
       done
       err=$?; [[ $err != 0 ]] && echo pid $BASHPID && exit $err
       echo "After the j loop."
done
echo "After all the loops."

輸出:

pid 31793 i 1
pid 31796 LINE root:x:0:0:root:/root:/bin/bash
pid 31796 LINE bin:x:1:1:bin:/bin:/sbin/nologin
pid 31796 LINE daemon:x:2:2:daemon:/sbin:/sbin/nologin
I've had enough!
pid 31793

變數“i”和“j”由 Fortran 提供。祝你今天過得愉快。:-)

引用自:https://unix.stackexchange.com/questions/213110