Working with Arrays in Linux Shell
One necessity is dealing with Arrays as a data structure in any kind of 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 (zsh).
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 with sh 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 with zsh 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 since the index in zsh starts with 1
- Iteration with index does not work for the zsh.
Resolve Issues
For the educational purpose, I use the variables INDEX_START
and INDEX_OFFSET
to accomplish identical results.
bash
Run bash 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
Run zsh 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)
For the popcorn geeks: