This post is older than a year. Consider some information might not be accurate anymore.
Used: bash v3.2 zsh 5.3
One necessity is dealing with Arrays as a data structure in any language or interpreter. The Linux Documentation Project has lots of documentation but lacks IMHO concise and straightforward examples. I created this example, as recently I have struggled myself how to operate on arrays. I spice it up with some ASCII art from asky.io (♥_♥)
.
The Example Program
I wrote this example on my MacBook Pro, which has two flavours of Linux Shell: Bash and Z shell.
There are minor differences in the feature set. The most important one:
- zsh arrays start at index position 1
- bash arrays start at index position 0
See a more detailed answer to that problem. Regardless pay attention, if you are using different shells.
Bash
Run withsh array-demo.sh
:detecting shell: using bash 3.2.57(1)-release array: ¯\_(ツ)_/¯ This is a string array ᕙ(⇀‸↼‶)ᕗ index 5: array length: 7 last index: ᕙ(⇀‸↼‶)ᕗ item: ¯\_(ツ)_/¯ has a length of 9 iterate over array ¯\_(ツ)_/¯ This is a string array ᕙ(⇀‸↼‶)ᕗ iterate with index index: 0, value: ¯\_(ツ)_/¯ index: 1, value: This index: 2, value: is index: 3, value: a index: 4, value: string index: 5, value: array index: 6, value: ᕙ(⇀‸↼‶)ᕗ
zsh
Run withzsh array-demo.sh
:detecting shell: using zsh 5.3 array: ¯\_(ツ)_/¯ This is a string array ᕙ(⇀‸↼‶)ᕗ index 5: string length: 7 last index: array item: has a length of 0 iterate over array ¯\_(ツ)_/¯ This is a string array ᕙ(⇀‸↼‶)ᕗThe major differences to bash:
- at index 5 the value is
string
instead ofarray
- the last value
array
is not correct, we expectᕙ(⇀‸↼‶)ᕗ
- the first item of index 0 is empty, the index in zsh starts with 1
Resolve Issues
For the educational purpose, I use the variables INDEX_START
and INDEX_OFFSET
to accomplish identical results.
bash
Runbash array-demo-improved.sh
detecting shell: using bash 3.2.57(1)-release, index starts at 0 array: ¯\_(ツ)_/¯ This is a string array ᕙ(⇀‸↼‶)ᕗ index 5: string length: 7 last index: ᕙ(⇀‸↼‶)ᕗ item: ¯\_(ツ)_/¯ has a length of 9 iterate over array ¯\_(ツ)_/¯ This is a string array ᕙ(⇀‸↼‶)ᕗ iterate with index index: 0, value: ¯\_(ツ)_/¯ index: 1, value: This index: 2, value: is index: 3, value: a index: 4, value: string index: 5, value: array index: 6, value: ᕙ(⇀‸↼‶)ᕗ
zsh
Runzsh array-demo-improved.sh
detecting shell: using zsh 5.3, index starts at 1 array: ¯\_(ツ)_/¯ This is a string array ᕙ(⇀‸↼‶)ᕗ index 5: string length: 7 last index: ᕙ(⇀‸↼‶)ᕗ item: ¯\_(ツ)_/¯ has a length of 9 iterate over array ¯\_(ツ)_/¯ This is a string array ᕙ(⇀‸↼‶)ᕗ iterate with index index: 1, value: ¯\_(ツ)_/¯ index: 2, value: This index: 3, value: is index: 4, value: a index: 5, value: string index: 6, value: array index: 7, value: ᕙ(⇀‸↼‶)ᕗ
Compare with diff
To compare the two outputs, if your eye doesn’t see the difference
diff <(sh array-demo-improved.sh) <(zsh array-demo-improved.sh)
Output:
2c2
< using bash 3.2.57(1)-release, index starts at 0
---
> using zsh 5.3, index starts at 1
24,30c24,30
< index: 0, value: ¯\_(ツ)_/¯
< index: 1, value: This
< index: 2, value: is
< index: 3, value: a
< index: 4, value: string
< index: 5, value: array
< index: 6, value: ᕙ(⇀‸↼‶)ᕗ
---
> index: 1, value: ¯\_(ツ)_/¯
> index: 2, value: This
> index: 3, value: is
> index: 4, value: a
> index: 5, value: string
> index: 6, value: array
> index: 7, value: ᕙ(⇀‸↼‶)ᕗ
Side by Side diff
diff -y <(sh array-demo-improved.sh) <(zsh array-demo-improved.sh)
Output:
detecting shell: detecting shell:
using bash 3.2.57(1)-release, index starts at 0 | using zsh 5.3, index starts at 1
array: ¯\_(ツ)_/¯ This is a string array ᕙ(⇀‸↼‶)ᕗ array: ¯\_(ツ)_/¯ This is a string array ᕙ(⇀‸↼‶)ᕗ
index 5: string index 5: string
length: 7 length: 7
last index: ᕙ(⇀‸↼‶)ᕗ last index: ᕙ(⇀‸↼‶)ᕗ
item: ¯\_(ツ)_/¯ has a length of 9 item: ¯\_(ツ)_/¯ has a length of 9
iterate over array iterate over array
¯\_(ツ)_/¯ ¯\_(ツ)_/¯
This This
is is
a a
string string
array array
ᕙ(⇀‸↼‶)ᕗ ᕙ(⇀‸↼‶)ᕗ
iterate with index iterate with index
index: 0, value: ¯\_(ツ)_/¯ | index: 1, value: ¯\_(ツ)_/¯
index: 1, value: This | index: 2, value: This
index: 2, value: is | index: 3, value: is
index: 3, value: a | index: 4, value: a
index: 4, value: string | index: 5, value: string
index: 5, value: array | index: 6, value: array
index: 6, value: ᕙ(⇀‸↼‶)ᕗ | index: 7, value: ᕙ(⇀‸↼‶)ᕗ
For the popcorn geeks:
Updates
2019-02-02: Got the use case for taking a random element from an array.
players=(dragon stegosaurus daemon kitty koala)
# get player with random index number from beginning to the size of array (1-5)
starter=${players[$RANDOM % ${#players[@]}]}
echo $starter