namerefs (introduced in bash 4.0) act as aliases for other variables
var=meow
declare -n ref=var
echo $ref # prints meow
ref=moo
echo $var # prints moo
they can also reference a specific element in an array, using
declare -n ref='array[1234]'
using this, i have been playing with a neat nameref trick:
tmp=()
declare -n var='tmp[tmp[0]=some_expression_here, 0]'
it uses the auxiliary array tmp to force an arithmetic context, in which it
assigns the result of any arbitrary expression to an element of that array,
then expands that same element. we can now create magic variables that
evaluate any arbitrary expression.
here's a basic counter:
tmp=()
x=0
declare -n counter='tmp[tmp[0]=x++,0]'
for i in {1..10}; do
echo $counter
done
# prints 0 1 2 3 4 5 6 7 8 9
here's an example that computes the fibonacci numbers:
f=(0 1)
declare -n fib='f[f[2]=f[0], f[0]+=f[1], f[1]=f[2], 0]'
for i in {1..10}; do
echo $fib
done
# prints 1 1 2 3 5 8 13 21 34 55
this is already very powerful, as it can do many magic things with numbers.
but as it turns out, we can do even more: we can use dollar expansions too!
here's a silly clock with magic variables that show the current date and time:
# \D{your-format-here} passes that format to strftime
# but it only works in prompts like $PS1
# ${var@P} expands $var as if it was in your $PS1
date=('\D{%'{Y,m,d,H,M,S}}) # the formats we'll use
months=(- jan feb mar apr may jun jul aug sep oct nov dec)
numbers=({00..60})
tmp=()
declare -n year='tmp[tmp=${date[0]@P},0]'
declare -n month='months[10#${date[1]@P}]'
declare -n day='numbers[10#${date[2]@P}]'
declare -n hour='numbers[10#${date[3]@P}]'
declare -n minute='numbers[10#${date[4]@P}]'
declare -n second='numbers[10#${date[5]@P}]'
while :; do
echo $year/$month/$day $hour:$minute:$second
sleep 1
done
# 2025/jun/06 09:54:13
# 2025/jun/06 09:54:14
# 2025/jun/06 09:54:15
# 2025/jun/06 09:54:16
this is probably one of the coolest things i've ever seen in bash.
honestly i am a bit horrified that this works at all, but the resulting code is
just so simple and elegant.
and it feels like i'm just scratching the surface, there's so much potential.
previous:
recursive expansions