如果函数内部条件失败,则在循环时跳过bash

时间:2018-11-16 20:39:45

标签: bash shell while-loop continue

我有一个while循环,它逐行读取文件,并将该行传递给循环内的多个函数或嵌套函数。如果函数之一发现错误,我希望while循环跳过该迭代并转到下一个迭代。

我确实做了很多搜索,并尝试了不同的方法,但是使用'continue跳过while循环是各处唯一的解决方案,但这似乎无济于事。我不确定在哪里或如何寻找这样的东西。是否存在解决此问题的解决方案或其他方法?感谢您的帮助。

   function2(){
   "if some condition that uses $test_name fails, skip the while loop"
  }

  function3(){
   do something
  }

  main_function (){
    do something to $test_name
    function2 $test_name
    function3 $test_name
  }

  while true read -r line; do
    if [[ ! "${line}" =~ ^# && ! -z "${line}" ]]; then
       test_name=$line
        main_function  $test_name 
    fi
 done < $OS_LIST

3 个答案:

答案 0 :(得分:2)

我愿意-

$: cat failout
#! /bin/env bash

OS_LIST=os_list

func1() {
  if [[ -z "$1" ]]
  then echo "ERROR - Empty string!"
       return 1
  fi
}

func2() {
  grep -q foo <<< "$1" || { echo "ERROR - no 'foo'!"; return 1; }
}

func3() { echo "all good here"; }

mainfunc() {
  func1 "$1" || return 1
  func2 "$1" || return 1
  func3 "$1" || return 1
}

while read -r line
do echo "before:[$line]"
   mainfunc "$line" || { echo test failed; continue; }
   echo all tests passed.
done < <( grep -Ev '^[[:space:]]*(#.*)*$' $OS_LIST )

请注意,循环会在读取之前使用grep消除注释和空行。

输入文件os_list,行号在

$: vi os_list
  1
  2
  3
  4   # shan't
  5
  6 foo bar other stuff
  7
  8 just foo
  9
 10 footed...
 11
 12 bar, without any required string!
 13
 14 more foo
 15
 16

为记录起见,其中一些空行确实有空格,有些则没有。 结果:

$: failout
before:[foo bar other stuff]
all good here
all tests passed.
before:[just foo]
all good here
all tests passed.
before:[footed...]
all good here
all tests passed.
before:[bar, without any required string!]
ERROR - no 'foo'!
test failed
before:[more foo]
all good here
all tests passed.

希望有帮助。肯定会更好。 欢迎提问。

答案 1 :(得分:2)

首先,编写函数,以便它们在失败时返回非零状态,在成功时返回零(实际上,作为一般的好习惯,您应该这样做)。像这样:

function2() {
    if some condition that uses $test_name fails; then
        echo "test condition failed in function2" >&2    # Error messages should be sent to stderr
        return 1
    fi
    # Code here will only be executed if the test succeeded
    do_something || return 1
    # Code here will only be executed if the test AND do_something both succeeded
    do_something_optional    # No error check here means it'll continue even if this fails
    do_something_else || {
        echo "do_something_else failed in function2" >&2
        return 1
    }
    return 0    # This is actually optional. By default it'll return the status
                # of the last command in the function, which must've succeeded
}

请注意,您可以根据情况在此处混合样式(if||与其他任何样式)。通常,请使用最清晰的样式,因为您的最大敌人就是对代码的工作感到困惑。

然后,在主功能中,您可以检查每个子功能的退出状态,如果其中任何一个失败,则提早返回:

main_function (){
    do something to "$test_name" || return 1    # BTW, you should double-quote variable references
    function2 "$test_name" || return 2    # optional: you can use different statuses for different problems
    function3 "$test_name"  || return 1
}

如果您需要跳过主循环的末尾,则可以使用continue

while true read -r line; do
    if [[ ! "${line}" =~ ^# && ! -z "${line}" ]]; then
        test_name=$line
        main_function "$test_name" || continue
        echo "Finished processing: $line" >&2    # Non-error status messages also go to stderr
    fi
done < "$OS_LIST"

答案 2 :(得分:1)

在功能2中,如果测试失败:

return 1

在主要功能中:

if [[ $? -eq 0 ]]; then
   function3 $test_name
else
   return
fi

希望它能提供帮助