While Do Loop and Variables in a Bash Script

A variable modified inside a while loop is not remembered


echo -e $lines | while read line 
...
done

The while loop is executed in a subshell. So any changes you do to the variable will not be available once the subshell exits.

Instead you can use a here string to re-write the while loop to be in the main shell process; only echo -e $lines will run in a subshell:

while read line
do
if [[ "$line" == "second line" ]]
then
foo=2
echo "Variable \$foo updated to $foo inside if inside while loop"
fi
echo "Value of \$foo in while loop body: $foo"
done <<< "$(echo -e "$lines")"

You can get rid of the rather ugly echo in the here-string above by expanding the backslash sequences immediately when assigning lines. The $'...' form of quoting can be used there:

lines=$'first line\nsecond line\nthird line'
while read line; do
...
done <<< "$lines"

While Do loop and variables in a bash script?

BASH FAQ entry #24: "I set variables in a loop. Why do they suddenly disappear after the loop terminates? Or, why can't I pipe data to read?"

store the while loop comparison as a variable

You can use a list in the test-commands portion of the while syntax, leaving the pertinent testing command for last; use that extra command to save the contents to a variable that you can test against later.

while curl_output="$(curl test.com/test)"; [[ "$curl_output" != "true" ]];
do
if [[ "$curl_output" == "stopping" ]] ;then
/etc/shutdown.sh # this script will change the output of $(curl test.com/test) to "true"
else
sleep "$sleep_timer"
fi
done

Shell variables set inside while loop not visible outside of it

When you pipe into a while loop in Bash, it creates a subshell. When the subshell exits, all variables return to their previous values (which may be null or unset). This can be prevented by using process substitution.

LONGEST_CNT=0
while read -r line
do
line_length=${#line}
if (( line_length > LONGEST_CNT ))
then
LONGEST_CNT=$line_length
LONGEST_STR=$line
fi
done < <(find samples/ ) # process substitution

echo $LONGEST_CNT : $LONGEST_STR

How do I read a variable on a while loop

You can write:

while IFS= read -r line
do
echo "$line"
done <<< "$the_list"

See §3.6.7 "Here Strings" in the Bash Reference Manual.

(I've also taken the liberty of adding some double-quotes, and adding -r and IFS= to read, to avoid too much mucking around with the contents of your variables.)

While loop in bash using variable from txt file

As indicated in the comments, you need to provide "something" to your while loop. The while construct is written in a way that will execute with a condition; if a file is given, it will proceed until the read exhausts.

#!/bin/bash
file=Sheetone.txt
while IFS= read -r line
do
echo sh /usr/local/test/bin/test -ID $line -I
done < "$file"
# -----^^^^^^^ a file!

Otherwise, it was like cycling without wheels...

Update global variable from while loop

That particular style of loop does not run in a sub-shell, it will update the variable just fine. You can see that in the following code, equivalent to yours other than adding things that you haven't included in the question:

USER_NonRecursiveSum=0

((USER_Num = 4)) # Add this to set loop limit.
((lineCount = 1)) # Add this to set loop control variable initial value.

while [ $lineCount -le $(($USER_Num)) ]
do
thisTime="1.2" # Modify this to provide specific thing to add.

USER_NonRecursiveSum=`echo "$USER_NonRecursiveSum + $thisTime" | bc`

(( lineCount += 1)) # Add this to limit loop.
done

echo ${USER_NonRecursiveSum} # Add this so we can see the final value.

That loop runs four times and adds 1.2 each time to the value starting at zero, and you can see it ends up as 4.8 after the loop is done.

While the echo command does run in a sub-shell, that's not an issue as the backticks explicitly capture the output from it and "deliver" it to the current shell.

While-loop over lines from variable in bash

You have several options:

  • A herestring (note that this is a non-POSIX extension): done <<<"$MY_VAR"
  • A heredoc (POSIX-compliant, will work with /bin/sh):

    done <<EOF
    $MY_VAR
    EOF
  • A process substitution (also a non-POSIX extension, but using printf rather than echo makes it more predictable across shells that support it; see the APPLICATION USAGE note in the POSIX spec for echo): done < <(printf '%s\n' "$MY_VAR")


Note that the first two options will (in bash) create a temporary file on disk with the variable's contents, whereas the last one uses a FIFO.

Bash: Retain variable's value after while loop

When you use a pipe you are automatically creating subshells so that the input and output can be hooked up by the shell. That means that you cannot modify the parent environment, because you're now in a child process.

As anubhava said though, you can reformulate the loop to avoid the pipe by using process substitution like so:

while read commit; do
TEMP_FLAG=true
done < <( git log --pretty="%H|%s" --skip=1 )

printf "%s\n" "$TEMP_FLAG"


Related Topics



Leave a reply



Submit