Operating System‎ > ‎Linux‎ > ‎Linux Shell Script‎ > ‎

06. Arrays and Strings (Part 1)

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

Creating / Initializing Array

  • 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

Accessing Arrays

  • 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

Length of an Array

  • 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

Extract Elements from an Array

  • 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

Adding Elements to an Array

  • 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

Removing Elements from an Array

  • 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


Search and Replace Elements in an Array

  • 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  


Access Each Element in an Array

  • 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


Store Multiple Input Data in an Array

  • 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


Comments