How to connect input to Bash while loop and save variables after loop completion

Bash allows you to use: cat <(echo "$FILECONTENT")

Bash also allows you to use: while read i; do echo $i; done </etc/passwd while read i; do echo $i; done </etc/passwd

you can use this to combine the previous two: echo $FILECONTENT | while read i; do echo $i; done echo $FILECONTENT | while read i; do echo $i; done

The problem with the latter is that it creates a sub-wrapper, and after the end of the while loop is not available, the variable i will no longer be available.

My question is:

How to achieve something like this: while read i; do echo $i; done <(echo "$FILECONTENT") while read i; do echo $i; done <(echo "$FILECONTENT") while read i; do echo $i; done <(echo "$FILECONTENT") or in other words: How can I be sure that i survives during the cycle?

Note that I am aware of the inclusion of the while expression in {} , but this does not solve the problem (imagine that you want to use the while while function and return the i variable)

+44
bash pipe while-loop stdin
Oct 24 '13 at 15:39
source share
2 answers

Correct Notation Replacement Process :

 while read i; do echo $i; done < <(echo "$FILECONTENT") 

The last value i assigned in the loop is available when the loop ends. An alternative is:

 echo $FILECONTENT | { while read i; do echo $i; done ...do other things using $i here... } 

Brackets are an I / O grouping operation and do not create a subshell themselves. In this context, they are part of the pipeline and therefore run as a subshell, but this is due to | , not with { ... } . You mentioned this in a question. AFAIK, you can make a return from within the function.




Bash also provides shopt built-in and one of its many options:

lastpipe

If set and job control is not active, the shell runs the last pipeline command that is not running in the background in the current shell environment.

Thus, using this type in a script makes modfied sum available after the loop:

 FILECONTENT="12 Name 13 Number 14 Information" shopt -s lastpipe # Comment this out to see the alternative behaviour sum=0 echo "$FILECONTENT" | while read number name; do ((sum+=$number)); done echo $sum 

Performing this on the command line is usually performed with the error "task management is inactive" (that is, task control is active on the command line). Testing this without using a script failed.

Also, as Gareth Rhys pointed out in his answer, you can sometimes use the line here :

 while read i; do echo $i; done <<< "$FILECONTENT" 

This does not require shopt ; You can save the process using it.

+55
Oct 24 '13 at 16:07
source share

Jonathan Leffler explains how to do what you want using process substitution , but another possibility is to use the line here :

 while read i; do echo "$i"; done <<<"$FILECONTENT" 

This saves the process.

+20
Oct 24 '13 at 16:14
source share



All Articles