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
EOFA process substitution (also a non-POSIX extension, but using
printf
rather thanecho
makes it more predictable across shells that support it; see the APPLICATION USAGE note in the POSIX spec forecho
):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
Using Bash Environment Variables from Within a Perl Script
Is Stack Memory Contiguous Physically in Linux
Matlab Mex Socket Wrapper Library
Eclipse Cdt Indexer Lost After System Update
How to Configure a Systemd Service to Restart Periodically
How to Delete First Two Lines and Last Four Lines from a Text File with Bash
How to Get Perf to Find Symbols in My Program
How to Pass a File Argument to My Bash Script Using a Terminal Command in Linux
Shell-Init: Error Retrieving Current Directory: Getcwd -- the Usual Fixes Do Not Wor
Genymotion Throws Libssl_Conf.So: Cannot Open Shared Object File: No Such File or Directory
Gcc: Putchar(Char) in Inline Assembly
Where Does Pp (Par) Unpack Add (-A) Files
Dyld_Library_Path Environment Variable Is Not Forwarded to External Command in Makefile on MACos
How to Not Transfer Changes Done to Files from a Branch to a Another in Git
How to Limit the Number of Results Returned from Grep
Backup a Running Docker Container