gawk: Walking Arrays

1 
1 10.7 Traversing Arrays of Arrays
1 ================================
1 
1 ⇒Arrays of Arrays described how 'gawk' provides arrays of arrays.
1 In particular, any element of an array may be either a scalar or another
1 array.  The 'isarray()' function (⇒Type Functions) lets you
1 distinguish an array from a scalar.  The following function,
1 'walk_array()', recursively traverses an array, printing the element
1 indices and values.  You call it with the array and a string
1 representing the name of the array:
1 
1      function walk_array(arr, name,      i)
1      {
1          for (i in arr) {
1              if (isarray(arr[i]))
1                  walk_array(arr[i], (name "[" i "]"))
1              else
1                  printf("%s[%s] = %s\n", name, i, arr[i])
1          }
1      }
1 
1 It works by looping over each element of the array.  If any given
1 element is itself an array, the function calls itself recursively,
1 passing the subarray and a new string representing the current index.
1 Otherwise, the function simply prints the element's name, index, and
1 value.  Here is a main program to demonstrate:
1 
1      BEGIN {
1          a[1] = 1
1          a[2][1] = 21
1          a[2][2] = 22
1          a[3] = 3
1          a[4][1][1] = 411
1          a[4][2] = 42
1 
1          walk_array(a, "a")
1      }
1 
1    When run, the program produces the following output:
1 
1      $ gawk -f walk_array.awk
1      -| a[1] = 1
1      -| a[2][1] = 21
1      -| a[2][2] = 22
1      -| a[3] = 3
1      -| a[4][1][1] = 411
1      -| a[4][2] = 42
1 
1    The function just presented simply prints the name and value of each
1 scalar array element.  However, it is easy to generalize it, by passing
1 in the name of a function to call when walking an array.  The modified
1 function looks like this:
1 
1      function process_array(arr, name, process, do_arrays,   i, new_name)
1      {
1          for (i in arr) {
1              new_name = (name "[" i "]")
1              if (isarray(arr[i])) {
1                  if (do_arrays)
1                      @process(new_name, arr[i])
1                  process_array(arr[i], new_name, process, do_arrays)
1              } else
1                  @process(new_name, arr[i])
1          }
1      }
1 
1    The arguments are as follows:
1 
1 'arr'
1      The array.
1 
1 'name'
1      The name of the array (a string).
1 
1 'process'
1      The name of the function to call.
1 
1 'do_arrays'
1      If this is true, the function can handle elements that are
1      subarrays.
1 
1    If subarrays are to be processed, that is done before walking them
1 further.
1 
1    When run with the following scaffolding, the function produces the
1 same results as does the earlier version of 'walk_array()':
1 
1      BEGIN {
1          a[1] = 1
1          a[2][1] = 21
1          a[2][2] = 22
1          a[3] = 3
1          a[4][1][1] = 411
1          a[4][2] = 42
1 
1          process_array(a, "a", "do_print", 0)
1      }
1 
1      function do_print(name, element)
1      {
1          printf "%s = %s\n", name, element
1      }
1