Shell scripts

3 minute read

On this page, I will capture all kinds of snippets that can be useful for different shell scripts. These scripts and examples are heavily copied from a site I lost the reference of (sorry about that!).

This is mainly targeted for Bash.

Arrays

Indexed arrays

1user $ declare -a Array
2user $ declare -a Array=(one two three)
3user $ Array=(one two three)

To add an element:

1user $ Array[4]='four'
2user $ Array+=( 'five' )

Associative arrays

1user $ declare -A Array
2user $ declare -A Array=( [one]=1 [two]=2 )

To add an element:

1user $ Array[one]=1
2user $ Array+=( [three]=3 [four]=4 )

How do I display the elements of an array?

To simply dump the values:

 1user $ echo ${Array[*]}
 2
 31 2 3 4
 4
 5user $ printf "Value: %s\n" "${Array[@]}"
 6
 7Value: 1
 8Value: 2
 9Value: 3
10Value: 4

How do I iterate on an array?

1user $ for value in "${Array[@]}"; do echo "$value"; done

How do I retrieve the keys of an array?

Please note that this also works with an indexed array:

1user $ declare -A Array
2user $ Array+=([one]=1 [two]=2 [three]=3)
3user $ for keys in "${!Array[@]}"; do echo "$keys"; done
4
5two
6three
7one

How to get the array size?

1user $ echo "Array size: ${#Array[*]}"
2
3Array size: 4

How to delete elements from an array?

1user $ declare -A Array=([one]=un [two]=deux [three]=trois)
2user $ echo ${Array[*]}
3
4deux trois un
5
6user $ unset Array[one]
7user $ echo ${Array[*]}
8
9deux trois

How to delete all elements of an array?

1user $ unset Array

Loops

1user $ for elem in 1 2 3 4; do ...; done
2user $ while read ...; do ...; done

A typical use of while read ... is to parse the output of a file or read from STDIN:

1user $ cat file.txt | while read line; do echo "$line"; done

The above command will simply echo each line but more complex actions can be taken for each line.

However, when doing so, Bash will spawn a new shell for the loop. This may have nasty consequences. Let’s take an example and let’s consider the following text file:

1This is a sentence.
2That is another one.
3I would like to have this.
4I don't like that.

The following script will go through the file and count the number of characters if the line contains the word “this”.

1i=0
2grep -i this file.txt|while read line; do
3    i=$(( $i + `echo "$line" | wc -m` ))
4    echo "Inside: " $i
5done
6echo "Outside: " $i

One might expect that the last output of Inside: would be the same as Outside:, however, if we run the code, this is what we’ll get:

1user $ sh test.sh
2
3Inside:  20
4Inside:  47
5Outside:  0

But why? Because as mentioned above, Bash will spawn a new shell for the loop.

So how could we solve this?

We need to use redirection for the loop! Here is how to solve this issue:

1i=0
2while read line; do
3    i=$(( $i + `echo "$line" | wc -m` ))
4    echo "Inside: " $i
5done < <(grep -i this file.txt)
6echo "Outside: " $i

The output will give us:

1user $ sh test.sh
2
3Inside:  20
4Inside:  47
5Outside:  47

VoilĂ ! The first < is used for redirection. The second < is used in conjunction with with ( to use the whole output of the () and send it to the while loop. Use that to show off at parties!