Overview
Often a script will need to work with a set of multiple data values
These data values can be input from the user or can be from the output of a utility through a pipe
It is useful to group these multiple data values into an array so we can easily refer to them as one group of data
The shell has multiple operations to support array manipulation
Similar to an array, a string is made up of multiple characters
Often we want to edit or extract just a part of the string
The shell has multiple operations to support string manipulation
Topics
Array operations
String manipulation operations
The bash shell supports one dimensional arrays
An array can contain more than one type of data (both numeric values and strings can be stored in one array)
Index values for an array starts at 0 and increments by 1
Index values can be a constant value, or can be the result of an arithmetic expression
Data in an array do not have to be at consecutive indexes
It’s possible to create an array with data at indexes 0, 3, 5, 8. Then if you access the array at index 1 or 2, you will get a null value
There are 2 ways to create an array and assign values to the array
First way:
arrayName=(value1 value2 value3 . . . )
value1 will be at index 0, value2 will be at index 1, and so on
values are listed with space as delimiter
Second way to create the same array:
arrayName[0]=value1
arrayName[1]=value2
arrayName[2]=value3 . . .
This way is most often accomplished with a loop
For both ways: If the values to be stored in the array contain spaces or other shell metacharacters, quote them to preserve these characters
To access one element of an array:
${arrayName[index]}
Example
classes=(cis18a cis18b cis18c)
echo ${classes[2]} print cis18c
To access all elements of an array:
${arrayName[@]} or ${arrayName[*]}
Example
echo ${classes[@]} print cis18a cis18b cis18c
echo ${classes[*]} print cis18a cis18b cis18c
Just as with command line arguments, the @ and * are only different when used within double quotes, where “[@]” is the list of individual elements, and “[*]” is a string containing all elements
If an array name is used without an index value, it refers to the first element of the array
Example: echo $classes print cis18a
To find the number of non-null elements of an array:
${#arrayName[@]}
Example
classes=(cis18a cis18b cis18c)
echo ${#classes[@]} print 3
To find the number of characters of one element of an array:
${#arrayName[index]}
Example
echo ${#classes[2]} print 6
Just like with filters, when the shell extracts data from an array or an element, it makes a copy and does not modify the array or element
To extract some particular elements from an array:
${arrayName[@]:startIndex:num}
where startIndex is the starting index, and num is the number of elements to extract
Example
classes=(cis18a cis18b cis18c cis22a cis22b cis22c)
echo ${classes[@]:2:3} print cis18c cis22a cis22b
To extract some particular characters of one element of an array:
${arrayName[index]:startChar:num}
where startChar is the starting character, num is the number of characters to extract, and character count starts at 0 for the start character
Example
echo ${classes[2]:2:4} print s18c
To add an element to an array: arrayName[index]=value
If index is larger than the last index of the array, then the new value is appended to the array
If index is less than or equal to the last index of the array, then the new value replaces an existing value in the array
Since the indexes don’t have to be continuous, it’s possible to add an element at an index which is much larger than the last index of the array
To append multiple elements to an array
arrayName=( ${arrayName[@]} value1 value2 value3 )
Example
classes=(cis18a cis18b)
classes=( ${classes[@]} cis33a cis33b )
echo ${classes[@]} print cis18a cis18b cis33a cis33b
classes[8] = cis18c cis18c is at index 8, values at indexes 4-7 are null
To join one array to another array:
array1=( ${array1[@]} ${array2[@]} $array3[@]} )
# array1is now made up of all elements of array1, followed by all elements of array2, then all elements of array3
To create a new array from other arrays:
newArray=( ${array1[@]} ${array2[@]} ${array3[@]} )
# newArray is made up of all elements of array1, followed by all elements of array2, then all elements of array3
Example
classes=(cis18a cis18b cis18c)
nums=(1 2 3)
classes=( ${classes[@]} ${nums[@]} )
echo ${classes[@]} print cis18a cis18b cis18c 1 2 3
To null an element of the array:
unset arrayName[index]
The value at index is now null, and ${#arrayName[@]} is smaller by 1
Example:
classes=(cis18a cis18b cis18c)
unset classes [1]
echo ${classes[1]} print nothing
echo ${#classes[@]} print 2 (size is smaller by 1)
To remove an entire array
unset arrayName
To search and replace an element in the array:
arrayName=( ${arrayName[@]/searchString/replacementString} )
Note the pattern is similar to the vi or sed substitute pattern
searchString is the what the shell will look for in the array. It can be a regular expression
replacementString is what the shell uses to replace the searchString if it’s found in an element of an array
Example:
classes=(cis18a cis18b cis18c cis26a )
classes=( ${classes[@]/18/25} )
echo ${classes[@]} print cis25a cis25b cis25c cis26a
To access each element in the array, use a for in loop
Example:
classes=(cis18a cis18b cis18c cis26a cis26b)
for class in ${classes[@]}
do
echo $class print each class in the array
done
Use an array to store multiple input data values
Example:
files=( `ls` )
for file in ${files[@]}
do
echo $file print each file in the current directory
done
Use an array to read multiple data values from the user
Use the –a option of read to store input data into an array
Example:
read -p “Enter numbers:” -a nums
for num in ${nums[@]}
do
echo $num print each number that user enters
done
Use an array to store data from a file
Example:
data=( `cat fileA` )
for val in ${data[@]}
do
echo $val print each value in fileA
done
Each value in the above example is a whitespace delimited word. So if each line in fileA has 8 words, and there are 5 lines total, then there will be 40 elements in the data array
To read a whole line into one element of an array, set the IFS shell variable to \n: IFS=$’\n’
IFS is for Input Field Separator – just like with awk
Example:
IFS=$’\n’
lines=( ‘cat fileA’ ) lines is an array with 5 elements
If each value of the file can be read in and processed one at a time, without having to keep track of all the values, then it is more efficient not to use an array
Alternate way to read data from a file, without using an array:
for val in `cat fileA`
do
echo $val print each value in fileA
done
The downside of not using an array is that val is overwritten each time a new value is read in from fileA