Magic Namerefs

14 hours ago 3

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

Read Entire Article