1. Overview
Assigning multiple variables in a single line of code is a handy feature in some programming languages, such as Python and PHP.
In this quick tutorial, we’ll take a closer look at how to do multiple variable assignment in Bash scripts.
2. Multiple Variable Assignment
Multiple variable assignment is also known as tuple unpacking or iterable unpacking.
It allows us to assign multiple variables at the same time in one single line of code.
Let’s take a look at a simple Python example to understand what multiple variable assignment looks like:
var1, var2, var3 = "I am var1", "I am var2", "I am var3"
In the example above, we assigned three string values to three variables in one shot.
Next, let’s prove if the values are assigned to variables correctly using the print() function:
print(var1)
I am var1
print(var2)
I am var2
print(var3)
I am var3
As the output shows, the assignment works as we expect.
Using the multiple variable assignment technique in Bash scripts can make our code look compact and give us the benefit of better performance, particularly when we want to assign multiple variables by the output of expensive command execution.
For example, let’s say we want to assign seven variables – the calendar week number, year, month, day, hour, minute, and second – based on the current date. We can straightforwardly do:
WEEK="$(date +'%W')"
YEAR="$(date +'%Y')"
MONTH="$(date +'%m')"
....
These assignments work well.
However, during the seven executions of the date commands, the current time is always changing, and we could get unexpected results.
Further, we’ll execute the date command seven times. If the command were an expensive process, the multiple assignments would definitely hurt the performance.
We can tweak the output format to ask the date command to output those required fields in one single shot:
$ date +'%W %Y %m %d %H %M %S'
08 2021 02 23 19 15 52
In other words, if we can somehow use the multiple variable assignment technique, we merely need to execute the date command once to assign the seven variables, something like:
WEEK YEAR MONTH DAY HOUR MINUTE SECOND="$(date +'%W %Y %m %d %H %M %S')"
Unfortunately, not all programming languages support the multiple variable assignment feature. Bash and shell script don’t support this feature. Therefore, the assignment above won’t work.
However, we can achieve our goal in some other ways.
Next, let’s figure them out.
3. Using the read Command
The read command is a powerful Bash built-in utility to read standard input (stdin) to shell variables.
It allows us to assign multiple variables at once:
$ read -r var1 var2 var3
100 200 300 #<- We input the values here
$ echo "var1=$var1; var2=$var2; var3=$var3"
var1=100; var2=200; var3=300
We use the -r option in the example above to disable backslash escapes when it reads the values.
However, the read command reads from stdin. It’s not so convenient to be used as variable assignments in shell scripts. After all, not all variables are assigned by user inputs.
But there are some ways to redirect values to stdin. Next, let’s see how to do it.
3.1. Using Process Substitution and IO Redirection
We know that we can use “*< FILE*” to redirect FILE to stdin. Further, process substitution can help us to make the output of a command appear like a file.
Therefore, we can combine the process substitution and the IO redirection together to feed the read command:
read -r var1 var2 var3 < <(COMMAND)
Let’s test it with the previous date command and seven variables’ assignment problem:
$ read -r WEEK YEAR MONTH DAY HOUR MINUTE SECOND < <(date +'%W %Y %m %d %H %M %S')
$ echo "week: $WEEK\nyear: $YEAR\nmonth: $MONTH\nday: $DAY\nhour: $HOUR\nminute: $MINUTE\nsecond: $SECOND"
week: 08
year: 2021
month: 02
day: 23
hour: 17
minute: 35
second: 17
As the output above shows, we’ve assigned seven variables in one shot using the process substitution and IO redirection trick.
3.2. Using Command Substitution and the Here-String
Alternatively, we can use the here-string to feed the stdin of the read command:
$ read -r var1 var2 var3 <<< "101 202 303"
$ echo "var1=$var1; var2=$var2; var3=$var3"
var1=101; var2=202; var3=303
If we replace the hard-coded string with a command substitution, we can set multiple variables using a command’s output.
Let’s test with the seven variables and the date command scenario:
$ read -r WEEK YEAR MONTH DAY HOUR MINUTE SECOND <<< "$(date +'%W %Y %m %d %H %M %S')"
$ echo "week: $WEEK\nyear: $YEAR\nmonth: $MONTH\nday: $DAY\nhour: $HOUR\nminute: $MINUTE\nsecond: $SECOND"
week: 08
year: 2021
month: 02
day: 23
hour: 19
minute: 26
second: 09
We’ve assigned seven variables in one shot. Also, the date command is executed only once.
Thus, the read command can help us to achieve multiple variables assignment.
3.3. Changing the Delimiter
The read command will take the value of the IFS variable as the delimiter. By default, it’s whitespace.
But we know that the output of a command is not always delimited by whitespace.
Let’s change the output format of the date command:
$ date +'%W@%F %T@%A'
08@2021-02-23 21:45:40@Tuesday
This time, the output is delimited by the ‘@’ character and has three fields: the week number, the current date and time, and the weekday of the current date. The second field contains a space.
Now, we’re about to assign the three fields to three variables in one shot.
Obviously, it won’t work with the default delimiter. We can change the delimiter by setting the IFS variable:
$ IFS='@' read -r WEEK_NO DATE_TIME WEEK_DAY <<< "$(date +'%W@%F %T@%A')"
$ echo "week_no: $WEEK_NO\ndate_time: $DATE_TIME\nweek_day: $WEEK_DAY"
week_no: 08
date_time: 2021-02-23 21:53:53
week_day: Tuesday
It’s worthwhile to mention that in the example above, the change to the IFS variable only affects the read command following it.
4. Using an Array
Another way to assign multiple variables using a command’s output is to assign the command output fields to an array.
Let’s show how it works with the date command and seven variables example:
$ readarray -d' ' -t ARR <<< "$(date +'%W %Y %m %d %H %M %S')"
$ echo -e "week: ${ARR[0]}\nyear: ${ARR[1]}\nmonth: ${ARR[2]}\nday: ${ARR[3]}\nhour: ${ARR[4]}\nminute: ${ARR[5]}\nsecond: ${ARR[6]}"
week: 08
year: 2021
month: 02
day: 23
hour: 22
minute: 19
second: 23
In the example, we used the Bash built-in readarray command to read the date command’s output.
The default delimiter used by the readarray command is a newline character. But we can set space as the delimiter using the -d option.
5. Conclusion
In this article, we’ve learned what the multiple variable assignment technique is.
Further, we’ve addressed how to achieve multiple variable assignment in Bash scripts through examples, even though Bash doesn’t support this language feature.