Bash Scripting – Does Bash Support Using Pointers?

bash

Simple question. Does the bash shell have any support for using pointers when writing a shell script?

I am familiar with expansion notation, ${var[@]} when iterating over the array $var, but it is not clear this is utilizing pointers to iterate over the array indices. Does bash provide access to memory addresses like other languages?

If bash does not support using pointers, what other shells do?

Best Answer

A pointer (to a location of memory) is not really a useful concept in anything higher-level than C, be it something like Python or the shell. References to objects are of course useful in high-level languages, perhaps even necessary for building complex data structures. But in most cases thinking in terms of memory addresses is too low level to be very useful.

In Bash (and other shells), you can get the values of array elements with the ${array[index]} notation, assign them with array[index]=... and get the number of elements in the array with ${#array[@]}. The expression inside the brackets is an arithmetic expression. As a made-up example, we could add a constant prefix to all array members:

for ((i=0 ; i < ${#array[@]} ; i++ )) ; do
    array[i]="foo-${array[i]}"
done

(If we only cared about the values, and not the indexes, just for x in "${array[@]}" ; do... would be fine.)

With associative or sparse arrays, a numerical loop doesn't make much sense, but instead we'd need to fetch the array keys/indexes with ${!array[@]}. E.g.

declare -A assoc=([foo]="123" [bar]="456")
for i in "${!assoc[@]}" ; do 
    echo "${assoc[$i]}"
done 

In addition to that, Bash has two ways to point indirectly to another variable:

  • indirect expansion, using the ${!var} syntax, which uses the value of the variable whose name is in var, and
  • namerefs, which need to be created with the declare builtin (or the ksh-compatible synonym, typeset). declare -n ref=var makes ref a reference to the variable var.

Namerefs also support indexing, in that if we have arr=(a b c); declare -n ref=arr; then ${ref[1]} will expand to b. Using ${!p[1]} would instead take p as an array, and refer to the variable named by its second element.

In Bash, namerefs are literally that, references by name, and using a nameref from inside a function will use the local value of the named variable. This will print local value of var.

#!/bin/bash
fun() {
        local var="local value of var"
        echo "$ref";
}
var="global var"
declare -n ref=var
fun

BashFAQ has a longer article on indirection, too.

Related Question