Tuesday, August 16, 2016

The Bash "Arrays"

  • Bash provides only 1 dimensional array.
     
  • Bash provides both indexed array and associative arrays(also called as hashes in other languages)

  • Any variables can be used as an indexed array.

  • The declare builtin can be used to explicitly declare an array.

  • There is no size limitations on array.

  • Indexed Arrays dont need the members be indexed or assigned continously.

  • Indexed arrays can be referenced using integers and are zero based.

  • Associative Arrays use arbitrary strings.

  • Following are two ways to create indexed arrays :
    • Implicit way : Assign Value to any variable using below syntax
name[subscript]=value
The subscript is treated as an arithmetic expression that must evaluate to a number.

  • Explicit way: Use declare -a
declare -a name

Examples:
  1. Implicit method:
[sukul1@lldd010 ~]$ array2[1]=sukul
[sukul1@lldd010 ~]$ array2[0]=mahadik
[sukul1@lldd010 ~]$  declare -a
declare -a BASH_ARGC='()'
declare -a BASH_ARGV='()'
declare -a BASH_LINENO='()'
declare -a BASH_SOURCE='()'
declare -ar BASH_VERSINFO='([0]="4" [1]="1" [2]="2" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -a DIRSTACK='()'
declare -a FUNCNAME='()'
declare -a GROUPS='()'
declare -a PIPESTATUS='([0]="0")'
declare -a array2='([0]="mahadik" [1]="sukul")'

  1. Explicit method:
[sukul1@lldd010 ~]$ declare -a array3
[sukul1@lldd010 ~]$ declare -a
declare -a BASH_ARGC='()'
declare -a BASH_ARGV='()'
declare -a BASH_LINENO='()'
declare -a BASH_SOURCE='()'
declare -ar BASH_VERSINFO='([0]="4" [1]="1" [2]="2" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -a DIRSTACK='()'
declare -a FUNCNAME='()'
declare -a GROUPS='()'
declare -a PIPESTATUS='([0]="0")'
declare -a array3='()'
[sukul1@lldd010 ~]$

The declare -a shows all the arrays defined in the current environment.

  • To create associative arrays we can use declare builtin.
declare -A name

Example:
[sukul1@lldd010 ~]$ declare -A AssoArray
[sukul1@lldd010 ~]$ declare -A
declare -A AssoArray='()'
declare -A BASH_ALIASES='()'
declare -A BASH_CMDS='()'
[sukul1@lldd010 ~]$


  • Attributes may be specified for an array variable using the declare and readonly builtins. Each attribute applies to all members of an array.
Thus we can make arrays readonly.

[sukul1@lldd010 ~]$ declare -A AssoArray
[sukul1@lldd010 ~]$ declare -A
declare -A AssoArray='()'
declare -A BASH_ALIASES='()'
declare -A BASH_CMDS='()'
[sukul1@lldd010 ~]$ declare -Ar readArray
[sukul1@lldd010 ~]$ readonly AssoArray
[sukul1@lldd010 ~]$ declare -A
declare -Ar AssoArray='()'
declare -A BASH_ALIASES='()'
declare -A BASH_CMDS='()'
declare -Ar readArray='()'
[sukul1@lldd010 ~]$

  • Once Arrays are created arrays can be assigned values one element at a time as shown below:

     
[sukul1@lldd016 ~]$ declare -a arr1
[sukul1@lldd016 ~]$ arr1[0]=25
[sukul1@lldd016 ~]$ arr1[1]=34
[sukul1@lldd016 ~]$ declare -A ARR1
[sukul1@lldd016 ~]$ ARR1['name']=sukul
[sukul1@lldd016 ~]$ ARR1['surname']=mahadik

Other simpler way to do this is to use compound assignments of the form
 
name=(value1 value2 ... )
 
where each value is of the form [subscript]=string. Indexed array assignments do not require anything but string.
When assigning to indexed arrays, if the optional subscript is supplied, that index is assigned to starts at zero.
When assigning to an associative array, the subscript is required.

Note that for indexed assigning values like this would implicitly create the array itself. However note that does not work with Associative arrays.
Associative arrays need to be created first before we do such compound assignment.

[sukul1@lldd016 ~]$ declare -a arr2
[sukul1@lldd016 ~]$ arr2=(23 45 23 21 56)
[sukul1@lldd016 ~]$ declare -a
declare -a arr2='([0]="23" [1]="45" [2]="23" [3]="21" [4]="56")'

[sukul1@lldd016 ~]$ declare -A ARR2
[sukul1@lldd016 ~]$ ARR2=([name]=sukul [surname]=mahadik)
[sukul1@lldd016 ~]$ declare -A
declare -A ARR2='([surname]="mahadik" [name]="sukul" )'

In below example we can see that compound assignment can actually create indexed array, but that does not work with associative arrays.
Associative arrays need declaration.

[sukul1@lldd016 ~]$ arr3=(p1 p2 p3 p4)
[sukul1@lldd016 ~]$ declare -a
declare -a arr3='([0]="p1" [1]="p2" [2]="p3" [3]="p4")'

[sukul1@lldd016 ~]$ ARR3=([surname]=mahadik)
[sukul1@lldd016 ~]$ declare -A
declare -A ARR1='([surname]="mahadik" [name]="sukul" )'
declare -A ARR2='([surname]="mahadik" [name]="sukul" )'
declare -A BASH_ALIASES='()'
declare -A BASH_CMDS='()'
[sukul1@lldd016 ~]$ declare -a
declare -a ARR3='([0]="mahadik")'
We can see above that associative array was not created implicitly using compound assignment method.
So remember that associative arrays need declaration.

  • When assigning to or referencing an indexed array, if name is subscripted by a negative number, that number is interpreted as relative to
one greater than the maximum index of name, so negative indices count back from the end of the array, and an index of -1 references the last element.

However for some reason this does not seem to work on my bash

[sukul1@lldd016 ~]$ echo ${arr2[1]}
45
[sukul1@lldd016 ~]$ echo ${arr2[-1]}
-bash: arr2: bad array subscript

[sukul1@lldd016 ~]$

  • Any element of an array may be referenced using ${name[subscript]}.
The braces are required to avoid conflicts with the shell’s filename expansion operators.
Remember that the braces are required. Ex: 2nd element of array arr2 is arr2[1] . So to check the value in it we need to put ${} around it, just as we do with variables.
But here remember that braces are always required.

  • If the subscript is ‘@’ or ‘*’, the word expands to all members of the array name.
These subscripts differ only when the word appears within double quotes.
If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS variable, and ${name[@]} expands each element of name to a separate word.

[sukul1@lldd016 ~]$ echo ${arr2[*]}
23 45 23 21 56
[sukul1@lldd016 ~]$ echo ${arr2[@]}
23 45 23 21 56

Following shows the difference between * and  when used in double quotes.
With * result is one single word.
[sukul1@lldd016 ~]$ for i in "${arr2[*]}"
> do
> echo $i
> done
23 45 23 21 56
[sukul1@lldd016 ~]$ for i in "${arr2[@]}"
> do
> echo $i
> done
23
45
23
21
56
[sukul1@lldd016 ~]$

This is analogous to the expansion of the special parameters ‘@’ and ‘*’.

  • ${#name[subscript]} expands to the length of ${name[subscript]}.
If subscript is ‘@’ or ‘*’, the expansion is the number of elements in the array.

Following shows how to find length of an element of array. Its no different that finding size of any other variable.

[sukul1@lldd016 ~]$ echo ${#ARR1[surname]}
7
[sukul1@lldd016 ~]$ echo ${ARR1[surname]}
mahadik
[sukul1@lldd016 ~]$

ARR1[surname] is nothing but a variable, just that this variable is part of any array.

Following shows how to find the size of array

[sukul1@lldd016 ~]$ echo ${#ARR1[*]}
2
[sukul1@lldd016 ~]$

  • Referencing an array variable without a subscript is equivalent to referencing with a subscript of 0.

[sukul1@lldd016 ~]$ echo ${arr2[0]}
23
[sukul1@lldd016 ~]$ echo $arr2
23
[sukul1@lldd016 ~]$

  • It is possible to obtain the keys (indices) of an array as well as the values.
${!name[@]} and ${!name[*]} expand to the indices assigned in array variable name.
The treatment when in double quotes is similar to the expansion of the special parameters ‘@’ and ‘*’ within double quotes.


[sukul1@lldd016 ~]$ echo ${!arr2[*]}
0 1 2 3 4

  • The unset builtin is used to destroy arrays. unset name[subscript] destroys the array element at index subscript.
unset name, where name is an array, removes the entire array. A subscript of ‘*’ or ‘@’ also removes the entire array

  • The declare, local, and readonly builtins each accept a -a option to specify an indexed array and a -A option to specify an associative array.
If both options are supplied, -A takes precedence.

  • The read builtin accepts a -a option to assign a list of words read from the standard input to an array, and can read values from the standard input into individual array elements.

  • The set and declare builtins display array values in a way that allows them to be reused as input.

No comments:

Post a Comment