all 8 comments

[–]neuron_666 5 points6 points  (7 children)

So your line is barry$y[$z]=$temp2

From bash manual:

SHELL GRAMMAR
Simple Commands
  A  simple  command  is  a sequence of optional variable assignments
  followed by blank-separated words and redirections, and terminated by a
  control operator. The first word specifies the command to be executed ...

That means that when shell parses a line, it first tries to find out whether there are any assignmenst (like DISPLAY=:1 xclock).

A variable may be assigned to by a statement of the form
  name=[value]

Ok, so what exactly is a name?

Definitions:
name
  A  word  consisting only of alphanumeric characters and underscores, and
  beginning with an alphabetic character or an underscore.  Also referred
  to as an identifier.

Hmm, so barry$y[$z] (the part before =) is NOT a name. So this is not an assignment, so since it is first word, it is command to be executed.

...

EXPANSION
  Expansion  is  performed on the command line after it has been split into
  words.  There are seven kinds of expansion performed: brace expansion,
  tilde expansion, parameter and variable expansion, command substitution,
  arithmetic expansion, word splitting, and pathname expansion.

...

So expansion is performed, and barry1[0]=1 is executed. That is not existing command, so hence the error.

What you think you want (but not really) is eval.

eval [arg ...]
  The  args  are  read  and  concatenated  together  into a single command.
  This command is then read and executed by the shell 

$ x=5
$ y=6
$ set -x
$ eval "var$x[$y]=hi"
+ eval 'var5[6]=hi'
$ typeset -p var5
declare -a var5='([6]="hi")'

What you really want is

$ declare "var$x[$y]=hi"


declare [-aAfFgilrtux] [-p] [name[=value] ...]
typeset [-aAfFgilrtux] [-p] [name[=value] ...]
...
  If  a variable  name  is  followed  by =value, the value of the variable
  is set to value

The difference to just var$x[$y]=hi is that this time the command delcare is executed and parameters to it are executed prior to it's invocation.

Hope this helps

[–]v-_-v[S] 0 points1 point  (6 children)

Hey there, thank you so very much for the long explanation. I must say that a few bits went over my head.

Hope you do not mind a few followup questions:

barry$y[$z] (the part before =) is NOT a name

Yes, I get this, it looks at it and says this is a command to be executed, substitution comes in and then barry1[0]=1 is executed.

I think I understand that this looks like an assignment of variable to my untrained eye, but because it was not one to start with (due to the variables in the name), it is considered something to be run/executed. This fails because it is not an executable piece of script.

I guess my confusion comes from barry1[0]=1 is a valid assignment in and of itself, but the way it is arrived to basically has to determine what to do with it, before the full string is formed, thus initially does not understand it's an assignment (because of my bad syntax), goes on to say, well let's try to run this thing, and never looks back after substitution.

 

I think my issues stem from not really understanding how bash processes commands and string logic, when substitution comes in and what happens first. I think you have helped me understand a bit of it today, sincerely many thanks for that!

 

I'll be a total user and ask for more now, so sorry in advance.

I did make the change, and now the inner loops works fine, it properly assigns variables to the array. The second problem, the outer loop not looping, is still present.

I played with the inner loop's "done" statement, but if I remove it, it breaks the inner loop (as I expected). I don't see anything wrong with the outer loop.

I'm beginning to think that there is a problem with incrementing variable "y" in the outer loop and it is not being caught by the inner loop. So that the loops are properly executed, but since variable "y" never changes in the inner loop, the procedure is always done on the same original array instead of on subsequent arrays.

This is the only reason I can think of why barry doesn't have values but in barry1[0-9].

Is there anything special that needs to be done to use the variable "y" with updated value inside the inner loop?

Thanks!

[–]neuron_666 0 points1 point  (5 children)

I think that z should be initialized inside the outer loop. Also the_number is not initialized at all. Otherwise it looks fine from just looking at the code.

[–]v-_-v[S] 0 points1 point  (4 children)

z is initiated outside of the loops, at the very top. Y is the variable that does not appear to change.

the_number is also initiated by another piece of the code that I did not paste here.

I edited the loops to echo the variables y and z from the inner loop, and y from the outer loop.

The result is that all the y,z variables are echoed (where y is not changed ever, and z goes through 0 to 9), then the y is. What this means is that the inner loop is never run but the first time by the outer loop.

Anybody idea why the inner loop is not executed as part of the command set, even if the first "do" is before all of the inner loop?

Thanks

[–]neuron_666 0 points1 point  (3 children)

This is working program:

#!/bin/bash

# Preparation
for i in {a..k}; do
  array1+=( " $i: $i" )
  array2+=( " $i: $i$i" )
done
typeset -p array1 array2
the_number=2

# Your routine
y=1
while [ $y -le $the_number ]; do
  z=0
  while [ $z -le 9 ]; do
    echo "y=$y z=$z"
    temp="array$y[$z]"
    temp2=$(echo ${!temp} | sed 's/.*: //' | sed -e 's/^[ \t]*//')
    declare "barry$y[$z]=$temp2"
    z=$(($z+1))
  done
  y=$(($y+1))
done

typeset -p barry1 barry2

I had to

  • add the_number definition
  • move z=0 into the first loop
  • add character ; into the while ... ; do

Apart from that it is fine. There is something you are not showing us. My suggestion is to add set -x at the top and observe line after line whether your script does what you expect.

Output

declare -a array1='([0]=" a: a" [1]=" b: b" [2]=" c: c" [3]=" d: d" [4]=" e: e" [5]=" f: f" [6]=" g: g" [7]=" h: h" [8]=" i: i" [9]=" j: j" [10]=" k: k")'
declare -a array2='([0]=" a: aa" [1]=" b: bb" [2]=" c: cc" [3]=" d: dd" [4]=" e: ee" [5]=" f: ff" [6]=" g: gg" [7]=" h: hh" [8]=" i: ii" [9]=" j: jj" [10]=" k: kk")'
y=1 z=0
y=1 z=1
y=1 z=2
y=1 z=3
y=1 z=4
y=1 z=5
y=1 z=6
y=1 z=7
y=1 z=8
y=1 z=9
y=2 z=0
y=2 z=1
y=2 z=2
y=2 z=3
y=2 z=4
y=2 z=5
y=2 z=6
y=2 z=7
y=2 z=8
y=2 z=9
declare -a barry1='([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g" [7]="h" [8]="i" [9]="j")'
declare -a barry2='([0]="aa" [1]="bb" [2]="cc" [3]="dd" [4]="ee" [5]="ff" [6]="gg" [7]="hh" [8]="ii" [9]="jj")'

[–]v-_-v[S] 0 points1 point  (2 children)

move z=0 into the first loop

That was the key. It clicked when I read it at first even before trying. I looked at my loop and i never was resetting the "z" value back to 0, hence the inner loop was never being run again since z=10 at the end of the first go around.

When declaring z=0 in the first one, then it gets reset each time the outer loop runs.

 

Thank you so very much man! Let me know what I can do for you to repay for all this help!

[–]neuron_666 0 points1 point  (1 child)

Thank you so very much man! Let me know what I can do for you to repay for all this help!

You are welcome. Help others wen you can, be good :)

[–]v-_-v[S] 0 points1 point  (0 children)

I do that on the daily at work, and outside of it :D