Preserve read statement's last variable assignments outside of "while" loop

I am trying to echo the variables $f1, $f2, … , outside of the while loop shown below. From what I understand, the scope of the variable is not correct. Therefore I tried a few of the workarounds as shown in the Bash FAQ:

while IFS=: read -r f1 f2 f3 f4 f5 f6 f7; do
  echo "Username: $f1. Home directory:$f6"
done</etc/passwd

echo $f1

However, I can’t seem to reproduce the fix(es) as shown in the link. Can someone provide an applied example on how to fix this issue?

Asked By: User

||

In your link, the variable used outside (linecount) is not defined as a “loop” variable. It’s just modified (incremented) inside the body loop, but not in the “while” statement.

This is because when the “read -r f1 f2…” part is called, it reset (prepare) the variables used (f1 ..f7), wait for an input line and assign the variables according to the input. At the end of the file, it does not get any input line (EOF or Pipe Error), returns false, and exits the loop. But it already has reset the variables.

You can figure it for yourself by enabling the “debug mode” by adding set -x before your while statement.

This will produce something like :

++ IFS=:
++ read -r f1 f2 f3 f4 f5 f6 f7
++ echo 'Username: bind. Home directory:/var/cache/bind'
Username: bind. Home directory:/var/cache/bind
++ IFS=:
++ read -r f1 f2 f3 f4 f5 f6 f7
++ echo

You can see the last read being called, then your final “echo $f1”.

So, as stated in your link, create another storage variable before your while, assign it the value and then you’ll be able to use it :

typeset f0=""
while IFS=: read -r f1 f2 f3 f4 f5 f6 f7; do
  echo "Username: $f1. Home directory:$f6"
  f0="$f1"
done</etc/passwd
echo $f0
Answered By: Adrien M.
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.