2

I have a Bash function, foo(), which will return 0 or 1 always. When it is returning 0, it would have produced some stdout:

foo() {
    if ...
      echo "aaa\nbbb"
      return 0
    else
      return 1
    fi
}

I want to repeatedly call this foo function, process its stdout, until it returns non-zero:

while foo; do
  # process foo's stdout that that one execution
done

But I don't know how to cleanly store the stdout of foo and use it in the while expression at the same time.

In ruby I might have done something like:

while text = self.foo do
  ...
end

Any suggestions? TIA

5 Answers 5

1

No one explained why your code doesnt work.

  1. Dont mix echo and return, use print(f) in combination with return instead. This will seperate function-stdout from function-signals.

  2. I would not recomment using a function to initiate a loop, because this way the function and loop will get called once only. You can run a infinity loop and break it when the requerments are met instead.

The code could look like this ...

#!/bin/bash

function foo() {
    if [ true = true ]; then    # some simple test
        printf "aaa\nbbb"   # stdout
        return 0    # singal (function status)
    else
        return 1
    fi
}

while true  # infinity loop
do
    STDOUT=$(foo)   
    ERRNO="$?"  # error number / return value / signal
    if [ "$ERRNO" -ne 0 ] ; then # -ne means Not Equal
        break   # end loop
    fi
    echo "$STDOUT"
done

exit "$ERRNO"   # exit with return value of foo

The output will look like this ...

aaa
bbb
aaa
bbb

till you hit ctrl-c or the function return is 1.

Sign up to request clarification or add additional context in comments.

3 Comments

Can you explain more about what you mean by "This will seperate function-stdout from function-signals"? Do you mean like, use echo only when one only wanting to print completely irrelevant text, but use printf to denote printing functional text, due to the fact that echo only returns 0 but printf can return non-0?
What I meant is echo may work in some cases, but when formating a text echo can remove backslashes and other symbols while using posix. printf on the other hand will always format a text like you want.
combine printf with return to make the function more solid.
1

I would change a bit the while like:

foo() {
    if (( $RANDOM % 5 ))
    then
        seq $(( $RANDOM % 10 ))
        return 0
    else
        return 1
    fi
}

while :
do
    #store the output to variable and check the return value
    var="$(foo)" || { echo no more input; exit 1; }
    echo got $(grep -c . <<<"$var") lines
done

it prints like:

got 9 lines
got 6 lines
got 4 lines
got 8 lines
got 2 lines
got 2 lines
no more input

Comments

1

The most obvious is to save it to a file:

foo() {
    if ...
      echo "aaa\nbbb"
      return 0
    else
      return 1
    fi
}

while foo > tmpfile; do
  # process tmpfile
done
rm tmpfile

Comments

1

A while can test a command, like the true or the false command:

 while false; do echo true ; done

...which outputs nothing. A while also acts the same way if the command is an assignment:

 while x=$(false) ; do echo true ; done

In the above code, the loop won't run, and $x is empty. Change it to x=$(true) and it runs echo true forever.

So it's like the ruby code:

while text = self.foo do

...except the syntax is:

while text=$(foo); do

Comments

0

You can use an infinite loop and break when foo() returns 1:

while : ; do
    out=$(func)
    [[ $? -eq 1 ]] && break
    # process the stdout of foo() here - which is stored in variable 'out'
    echo $out
done

1 Comment

echo "$out" looks better.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.