Monday, May 8, 2006

BASHing to Bake a Pointer

The BASH has become so powerful that 'pointers' can be implemented in that. Here is a small how-to on how to simulate pointers and surprisingly, you can have any level deep of pointer reference. But, dont expect too much in this, for this has to be taken as an analogy to pointer concepts and not to be taken as exact replica of the one thats done in C/C++.

HERE IS HOW TO CREATE A POINTER:

# Dont get annoyed, you can only get cheese with the milk not a pizza!

$ some_var=1729
$ some_pointer="some_var"

SOME EXPERIMENTS:
Now that the pointer variable, "some_pointer" has been created, here is how to de-reference it to get the value. This was quite interesting coz, as we imagine, the things like '$$var' and '${$var}' doesnot workout that well.

First job is to make variable get work properly. We give a variable by name, say, "some_var" and we ought to see the value "1729", so here is a try.

# This is the one we know already.

$ echo $some_var

...

# All other methods, are in vain :(

$ echo $$some_var # Really bad
$ echo '$'$some_var # Seems convincing..
$ echo ${$some_var} # Pathetic
...

# And finally, here comes a method, to
# refer to the value of a given variable name.
# Lets put that as a function

$ function _() { eval echo $`echo $1`; }

# Here comes...

$ _ some_pointer
some_var
$ _ some_var
1729
$

# Bingo.. things seems to work :)

DE-REFERENCING THE VARIABLE:
Now we have the variable de-reference function. Here we go.


$ function _() { var=$(eval echo $`echo $1`); eval echo $`echo $var`; }
$ _ some_pointer
1729
$ echo "BINGO! THAT WORKED!!!"
bash !": event not found

# A lil too much crazy :)

HANDLING ARRAYS IN BASH:
Now comes the best part with the 'Arrays'.

# Here is how to create an array.. requires no energy actually.

$ myarr[1]="hello"
$ myarr[2]="world"
$ myarr[3]='missing (L|W|KN)IFE'
$ myarr[fun]="really"

# Now to access an element, we should be doing this.

$ echo ${myarr[1]} # Or even as
$ echo ${myarr[fun]}

# Here is how to count the total number of elements

$ echo ${#myarr}
$ echo ${#myarr[fun]} # This gives the length.

# Here is how to access all elements in one go..

$ echo ${myarr[*]}
$ echo ${myarr[@]}

# But what is the difference? You might ask, so, try this:

$ for each elem in "${myarr[*]}"
> do
> echo "*" $elem "*"
> done
$ for each elem in "${myarr[@]}"
> do
> echo "*" $elem "*"
> done

# The difference should be visible :)

POINTER TO AN ARRAY:
Here we turn around to fix up our actual task of implementing pointer, we should be complete isn't? So, we also do the work of simulating pointer to an array (sounds lot of fun..).

Here is how we access n'th element of an array, or in short given a subscript and an array name, we access its value.

# For now, we limit ourself by denoting the array and subscript by variables.

$ a_var="myarr"
$ a_sub="fun"
$ eval echo '${'$a_var"[$a_sub]"'}'
really
$

# We are ready with the mode of attack and here goes our function.

$ function _() {
> a_var=$(eval echo $`echo $1`)
> a_sub=$(eval echo $`echo $2`)
> eval echo '${'$a_var"[$a_sub]"'}'
> }
$ _ a_var a_sub
really
$

# Its done :)

LIMITATIONS...
This is not the limitations of the BASH pointer simulation rather, limitation on the content side in Blog. Planning to write a complete pointer simulation script for BASH and hope to put that soon in my Wiki.

2 comments:

Robert Mark Bram said...

Hi,

That pointer to an array doesn't seem right.

myarr[1]="hello"
myarr[2]="world"
myarr[3]='missing (L|W|KN)IFE'
myarr[fun]="really"
myarr[fun2]="really2"
a_var="myarr"
a_sub="fun"
hh=`eval echo '${'$a_var"[$a_sub]"'}'`
echo $hh


Output:
really2

Robert Mark Bram said...

Try this instead - using Indirect variable references in Bash 2.

myarr=(
fun1="really1"
fun2="really2"
)

local ${myarr[*]}
echo ${fun1}
echo ${fun2}

myarr2=(
fun3="really3"
fun4="really4"
)

arrayName=myarr2[*]
elementName1=fun3
elementName2=fun4

local ${!arrayName}
echo ${!elementName1}
echo ${!elementName2}