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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.