Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is return handled in a function while loop?

I have a function, and inside that function is a while loop.

When I try to set a non local variable inside the while loop with an IF statement, then exit the entire function, suddenly the variable is no longer set?

function EXAMPLE {
  cat test.txt | while read LINE; do
    if [ "$LINE" = "FAIL" ]; then
      echo "Detected FAIL in file! Setting RETURN=fail and exiting function."
      RETURN="fail"
      return
    fi
  done
}

### START SCRIPT ###
EXAMPLE (Call example function)
echo "$RETURN"

For some reason, RETURN is empty. I have done this many many many times in the past though. Something about the while loop is preventing RETURN from being passed out of the function. Is "return" causing the script to break the loop and not the function?

Thanks

like image 447
Atomiklan Avatar asked Oct 15 '25 02:10

Atomiklan


2 Answers

The easiest solution is to avoid the subshell in the first place, by using input redirection instead of a pipeline.

function EXAMPLE {
  while IFS= read -r line; do
    if [ "$line" = "FAIL" ]; then
      echo "Detected FAIL in file! Setting RETURN=fail and exiting function."
      RETURN="fail"
      return
    fi
  done < test.txt
}

In cases where the pipeline is unavoidable, bash 4.2 introduced the lastpipe option, which when enabled allows the last command in a pipeline to run in the current shell, not a subshell. This way, the value assigned to RETURN would be retained after the pipeline completes.

Even better, use the standard mechanism for signaling an error. Instead of setting the value of a custom parameter, just return a non-zero value:

function EXAMPLE {
  while IFS= read -r line; do
    if [ "$line" = "FAIL" ]; then
      echo "Detected FAIL in file! Exiting function with status 1."
      return 1
    fi
  done < test.txt
}
like image 142
chepner Avatar answered Oct 17 '25 16:10

chepner


When you use a pipeline in bash, all the commands within the pipeline are executed in subshells. That means variables cannot survive when the subshell exits. In this cate it's easy to remove the pipe

function EXAMPLE {
  while read LINE; do
    if [ "$LINE" = "FAIL" ]; then
      echo "Detected FAIL in file! Setting RETURN=fail and exiting function."
      RETURN="fail"
      return
    fi
  done < text.txt
}

I'd recommend not using ALL CAPS so often: one day you'll use a variable named PATH and then have to figure out why commands stop working.

like image 35
glenn jackman Avatar answered Oct 17 '25 16:10

glenn jackman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!