This question already has answers here:
A variable modified inside a while loop is not remembered
(8 answers)
Closed 2 years ago.
I am trying to add elements to an array in bash. I am querying and looping over the query.
delete_arr=()
delete_arr+=("test")
mysql -e "$sql_statement" | while read directory_name; do
if [ $counter -gt 0 ]
then
delete_arr+=($directory_name)
fi
let counter=counter+1
done
for i in "${delete_arr[*]}"; do echo "$i"; done
The only output I am getting is test. I should be getting a lot more data. The query works and the data gets added to the array in the loop however when I jump out of the loop the array only contains test.I am doing nothing to reset the array.
In the pipe, you are implicitly creating a new subshell with its own namespace. Try avoiding the pipe:
delete_arr=()
delete_arr+=("test")
while read directory_name
do
if [ "$counter" -gt 0 ]
then
delete_arr+=("$directory_name")
fi
counter=$((counter+1))
done < <(mysql -e "$sql_statement")
for i in "${delete_arr[#]}"; do echo "$i"; done
Related
This question already has answers here:
A variable modified inside a while loop is not remembered
(8 answers)
Closed 2 years ago.
I am trying to insert values in to an array in a loop as follows:
branches_to_delete=()
cat branches.txt | while read branch_name
do
BRANCH_COUNT=$(git ls-remote | grep -w $branch_name | wc -l)
if [ $BRANCH_COUNT -eq 0 ]; then
echo "Branch does not exist"
branches_to_delete+=($branch_name)
elif [ $BRANCH_COUNT -eq 1 ]; then
echo "Branch exists"
else
echo "Not valid result"
fi
done
echo "Loop finished"
echo ${branches_to_delete[#]}
But when I printout branches_to_delete it is actually empty.
What am I doing wrong here?
With the pipe from cat branches.txt into the read loop, you create a subshell that cannot access the parent shell's branches_to_delete array.
You can fix this by avoiding the pipe and saving a useless use of cat:
branches_to_delete=()
while read branch_name; do
...
done < branches.txt
(Make sure nothing in ... reads from read's stdin. You'll notice if something is missing).
This question already has answers here:
A variable modified inside a while loop is not remembered
(8 answers)
Closed 4 years ago.
I have this:
ql_remove_locks(){
local pid="$$";
declare -i count=0;
ql_pid="$pid" ql_node_ls_all | while read line; do
count=$((count+1));
echo "count: $count";
echo "deleting lock: $line";
rm -rf "$line";
done;
echo "quicklock: $count lock(s) removed."
}
I am getting this output:
count: 1
deleting lock: /Users/alexamil/.quicklock/locks/a.lock
quicklock: 0 lock(s) removed.
I have tried so many things, still 0 always gets logged:
quicklock: 0 lock(s) removed.
Why is the count 0 instead of 1 in the echo statement?
Commands in a pipeline are run in subshells. The while loop is in a subshell, with its own copies of variables, and modifying $count there doesn't propagate back to the parent shell.
You can switch the pipe to a redirection + process substitution to work around this.
while read line; do
count=$((count+1))
echo "count: $count"
echo "deleting lock: $line"
rm -rf "$line"
done < <(ql_pid="$pid" ql_node_ls_all)
NB: The semicolons are superfluous.
This question already has answers here:
A variable modified inside a while loop is not remembered
(8 answers)
Closed 5 years ago.
Problem
My bash script loops through a bunch of files and if it finds an unexpected file that contains some text, it sets an error flag and is supposed to exit the loop. The problem is that when i evaluate the error condition after the loop, the error flag isn't set properly.
I can't seem to see where the bug is.
Code
#!/bin/sh
valid=1
grep -rs -L 'bogustext' * | while read line; do
echo "Processing file '$line'"
if [ "$line" != "arc/.keep" ] && [ "$line" != "arc/prp/lxc" ] && [ "$line" != "arc/lbb/lxc" ]; then
valid=0
echo "just set it to zero - $valid"
break 2
fi
done
echo "$valid"
if [ "$valid" -eq 0 ]; then
echo "1..1"
echo "not ok $line invis malformed"
else
echo "1..1"
echo "ok"
fi
Here's the output which shows the problem / bug. As you can see, there is an extra file in the list that contains the bogus string "arc/ttp". The script sets the "valid" variable to 0 but by the time I'm ready to evaluate it to display the right status, it's still the original value.
lab-1:/var/vrior# sh test.sh
Processing file 'arc/.keep'
Processing file 'arc/prp/lxc'
Processing file 'arc/lbb/lxc'
Processing file 'arc/ttp'
just set it to zero - 0
1
1..1
ok
What I've tried so far
I'm currently googling to see if in Bash there's local variables vs. global. Not too sure, but if you see my bug, please let me know.
Pipes create subshells, so $valid inside the loop refers to a new variable, which disappears before you try and use it.
Since you've tagged bash, then you can use a process substitution instead of the pipe:
while read line; do
echo "Processing file '$line'"
if [ "$line" != "arc/.keep" ] && [ "$line" != "arc/prp/lxc" ] && [ "$line" != "arc/lbb/lxc" ]; then
valid=0
echo "just set it to zero - $valid"
break 2
fi
done < <(grep -rs -L 'bogustext' *)
This question already has answers here:
Dynamic variable names in Bash
(19 answers)
Closed 7 years ago.
This one is probably pretty simple. I've got a simple while loop which asks the user to input data
while [ $i -le $numMasterNodes ]; do
echo "Enter hostname #$i: "
read masterHost$i
((i+=1))
done
I'm trying to get the value of $masterHost$i in my loop, for example
while [ $i -le $numMasterNodes ]; do
echo "Enter hostname #$i: "
read masterHost$i
echo $masterHost$i
((i+=1))
done
However, it just returns 1 2 3, etc... How can I get the value of $masterHost$i so I can add it to an array?
Thanks!
You probably would be happier with an array. See http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_10_02.html
Note if you already know about arrays, I'm not sure why you're not just using one directly in your loop.
Here's your example recoded to do that:
#!/bin/bash -
i=1
numMasterNodes=3
declare -a masterHost
while [ $i -le $numMasterNodes ]; do
echo "Enter hostname #$i: "
read masterHost[$i]
echo ECHO ${masterHost[$i]}
((i+=1))
done
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Bash Script - Variable Scope in Do-While loop
In the following code, it prints the correct value of i in inner while loop, but it prints 0 after it comes out of inner while loop:
string="Medicine"
for file in *
do
i=0
cat $file | while read line
do
echo $line
if [ "$line" == "$string" ];
then
i=`expr $i + 1`
echo $i
fi
done
echo $i
done
By default variables have global scope in shell scripting, which make "i " global. if you want to make a variable as local ,use keyword "local" , for eg: local i=0
for more details check the link, http://www.bashguru.com/2008/06/bash-variables-scope.html