Hi,
I am attempting to assign the output of the following command, to two bash variables, var1 and var2 using "read," but it doesn't seem to be working.
[root@xxx ~]# openstack hypervisor stats show | awk -F'|' 'NR==14{print $2,$3}'
vcpus 92
[root@xxx ~]# echo $?
0
[root@xxx ~]# openstack hypervisor stats show | awk -F'|' 'NR==14{print $2,$3}' | read var1 var2
[root@xxx ~]# echo $var1
[root@xxx ~]# echo $var2
Could I get some guidance around what is happening here?
I'm familiar with using var1=$(awk ...)
to assign output to a bash variable, but wanted to see how it's done with read.
Thanks.
This is because commands within a pipeline are run in subshells so the read statement is setting the variables is a subshell which has not impact on the main shell.
You can achieve what you want using process substitution like this:
# read var1 var2 < <(openstack hypervisor stats show | awk -F'|' 'NR==14{print $2,$3}')
# echo $var1
vcpus
Edit:
Also in bash 4.* and later you can use a shell option to run the last pipeline command in the current shell.
Note this only work for shells without job control, so in an interactive shell (as opposed to a script) you will also need turn off job control ( set +m
).
# echo $BASH_VERSION
5.0.7(1)-release
# shopt -s lastpipe
# set +m
# echo A B C | head -1 | read first second rest
# echo $first
A
# set -m
# shopt -u lastpipe
2 Likes
Hi Chubler_XL,
Appreciate the clarification.
What is the purpose of two "<" ? Does it mean that each value from awk will be assigned to the bash variable, with whitespace as delimiter?
Thanks.
the first <
is a standard input redirection and causes input to the read command to come from a file.
The second part is process substitution witch takes the format of <(list)
. The value list
can be a command or a pipeline of commands which is executed and the output is a file name of a named pipe that contains the output of list
.
2 Likes
Here are some more alternatives to try:
Use a here string
read var1 var2 <<< "$(openstack hypervisor stats show | awk -F'|' 'NR==14{print $2,$3}')"
Use a here document
read var1 var2 << EOB
$(openstack hypervisor stats show | awk -F'|' 'NR==14{print $2,$3}')
EOB
Use a code block (the variables can be used inside the code block)
openstack hypervisor stats show | awk -F'|' 'NR==14{print $2,$3}' |
{
read var1 var2
echo "$var1"
echo "$var2"
}
Use the if statement as block and test if the variables are being read (the variables can be used inside the if statement).
openstack hypervisor stats show | awk -F'|' 'NR==14{print $2,$3}' |
if read var1 var2; then
echo "$var1"
echo "$var2"
fi
1 Like