Linux bash: Multiple variable assignment
First thing that comes into my mind:
read -r a b c <<<$(echo 1 2 3) ; echo "$a|$b|$c"
output is, unsurprisingly
1|2|3
Bash: How to split a string and assign multiple variables
x="http://web.com/sub1/sub2/sub3/sub4/sub5/sub6"
IFS="/" read -r foo foo foo foo var1 foo var2 var3 foo <<< "$x"
echo "$var1 $var2 $var3"
Output:
sub2 sub4 sub5
Or with an array:
x="http://web.com/sub1/sub2/sub3/sub4/sub5/sub6"
IFS="/" read -r -a var <<< "$x"
echo "${var[4]}"
declare -p var
Output:
sub2
declare -a var='([0]="http:" [1]="" [2]="web.com" [3]="sub1" [4]="sub2" [5]="sub3" [6]="sub4" [7]="sub5" [8]="sub6")'
From man bash
:
IFS
: The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command.
Bash multiple variable assignment
The output of curl
contains some \r
characters,
that's why the output looks messed up.
You can get rid of it by inserting a tr -d '\r'
into the pipeline after the curl
and before the egrep
.
Is it really important to read into RESP
and DATE
variables?
You could use Awk to extract the interesting parts simpler, saner,
and output directly in the desired format:
curl ... | tr -d '\r' | awk '/^< Date: / { date = substr($0, 9); print "[" date "] " resp } /^< HTTP\// { resp = $3 }'
How to read variables from file, with multiple variables per line?
I think all you're looking for is to read multiple variables per line: the read
command can assign words to variables by itself.
while read -r first second third; do
do_stuff_with "$first"
do_stuff_with "$second"
do_stuff_with "$third"
done < ./test.txt
using jq to assign multiple output variables
You can use separate variables with read
:
read var1 var2 var3 < <(echo $(curl -s 'https://api.github.com/repos/torvalds/linux' |
jq -r '.id, .name, .full_name'))
echo "id : $var1"
echo "name : $var2"
echo "full_name : $var3"
Using array :
read -a arr < <(echo $(curl -s 'https://api.github.com/repos/torvalds/linux' |
jq -r '.id, .name, .full_name'))
echo "id : ${arr[0]}"
echo "name : ${arr[1]}"
echo "full_name : ${arr[2]}"
Also you can split jq output with some character :
IFS='|' read var1 var2 var3 var4 < <(curl '......' | jq -r '.data |
map([.absoluteNumber, .airedEpisodeNumber, .episodeName, .overview] |
join("|")) | join("\n")')
Or use an array like :
set -f; IFS='|' data=($(curl '......' | jq -r '.data |
map([.absoluteNumber, .airedEpisodeNumber, .episodeName, .overview] |
join("|")) | join("\n")')); set +f
absoluteNumber
, airedEpisodeNumber
, episodeName
& overview
are respectively ${data[0]}
, ${data[1]}
, ${data[2]}
, ${data[3]}
. set -f
and set +f
are used to respectively disable & enable globbing.
For the jq part, all your required fields are mapped and delimited with a '|'
character with join("|")
If your are using jq < 1.5, you'll have to convert Number to String with tostring
for each Number fields eg:
IFS='|' read var1 var2 var3 var4 < <(curl '......' | jq -r '.data |
map([.absoluteNumber|tostring, .airedEpisodeNumber|tostring, .episodeName, .overview] |
join("|")) | join("\n")')
Echo multiple variables via single command in Bash
It'd probably be easier to use an array instead of numbered variables:
my_web=(
"some value1"
"some value2"
"some value3"
)
Then to print them like you want:
(IFS=$'\n'; echo "web at ${my_web[*]:0:3}")
This temporarily sets the "internal field separator" to a newline so that when we join the array elements (my_web[*]
), it joins them on the newline. I'm also explicitly selecting the first three elements, but you don't actually need to do that in this case since those are the only elements that exist.
Note that Bash arrays are 0-indexed.
Due credit to Glenn Jackman's now-deleted answer for inspiring this echo
command.
How to assign multiple variables to a FIXED sized table output
As you are relying on the word splitting
in the read
command,
succesive empty values are put together to cause inconsistency in the result.
Would you please try instead:
# no changes in your original template
template="General;%OverallBitRate/String%|
Video;%Width%|%Height%|%FrameRate/String%|%DisplayAspectRatio/String%|%ScanType/String%|%FrameRate/String%|%ChromaSubsampling/String%|%BitDepth%|%InternetMediaType%|%Format/String%|%Format_Profile%|%Format_Settings%|%BitRate_Mode/String%|%BitRate_Nominal/String%|%BitRate_Maximum/String%|%ColorSpace%|
Audio;%BitRate/String%|%Format/String%|%Channel(s)/String%|%BitRate_Mode/String%|%BitRate/String%|%SamplingRate/String%"
mapfile -t info < <(mediainfo --Output="$template" "$1" | sed 's/video\///g' | tr '|' '\n' | awk '{ print $1 }')
for i in "${info[@]}"; do
echo "$i"
done
The mapfile
built-in command reads lines from the standard input
assigning an array (info
here) to each lines.
It preserves the empty line as is
then the result has always the same length.
If you want to assign individual scalar variables to the elements of the array,
you can say something like:
A="${info[0]}"
B="${info[1]}"
C="${info[2]}"
...
although it would be more convenient to treat the array as an array.
Check if multiple Bash variable are empty/not set and run this or that
Use just -z $VAR
if [[ -z $VAR1 || -z $VAR2 ]]; then
echo "VARs NOT set -- "
cat <<EOF > file
1
2
3
EOF
else
echo "VARs are set"
cat <<EOF > file
1
2
3
4
5
EOF
fi
Related Topics
How to Turn Off Echo While Executing a Shell Script Linux
Linux: Find File Names With 4 or 5 Characters
What Is the Meaning of "Posix"
How to Change the Root Directory of an Apache Server
Multiple Glibc Libraries on a Single Host
What's the Best Way to Send a Signal to All Members of a Process Group
How to Write Standard Error to a File While Using "Tee" With a Pipe
How to Convert Dos/Windows Newline (Crlf) to Unix Newline (Lf)
How to Keep Environment Variables When Using Sudo
How to Store a Command in a Variable in a Shell Script
How to Grep For Contents After Pattern
How to Get Cron to Call in the Correct Paths
What Is the Meaning of So_Reuseaddr (Setsockopt Option) - Linux
How to Use Sed to Extract Substring
Kdevtmpfsi Using the Entire Cpu