I have a while loop that reads a file line by line and pass the line to multiple functions or nested functions inside the loop. if one of the function finds something wrong I want the while loop to skip that iteration and go to the next one.
I did search a lot and tried different things but using 'continue to skip the while loop was the only solution everywhere but it doesn't seem to be helping. I am not sure where or how to look for something like this. Is there a solution or a different approach to solving this issue? Thanks for any help.
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
First, write the functions so that they return a nonzero status if they fail, zero if they succeed (actually, you should be doing this anyway as a general good practice). Something like this:
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
}
Note that you can mix styles here (if
vs ||
vs whatever) as the situation warrants. In general, use the style that's clearest, since your biggest enemy is confusion about what the code's doing.
Then, in the main function, you can check each sub-function's exit status and return early if any of them fail:
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
}
If you need to skip the end of the main loop, that's where you'd use 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"