How to reassign new values to array elements?

57,824

I would be suspicious of your version of Bash to start. I'm on this version and I can set arrays just fine.

$ bash --version
GNU bash, version 4.2.45(1)-release (x86_64-redhat-linux-gnu)

Example

$ array[0]=0
$ array[1]=1
$ array[2]=2

You can then recall them individually:

$ echo ${array[0]}
0

$ echo ${array[1]}
1

$ echo ${array[2]}
2

Or as a list:

$ echo "${array[@]}"
0 1 2

You cannot just call the array as another variable:

$ echo $array
0

I believe this may have been what was misleading you into thinking it wasn't working correctly. Also setting an array element with another variable's value also works.

Example

$ newval=3
$ array[2]=$newval

$ echo "${array[@]}"
0 1 3

You could also use printf here, doing so will show you why you want to quote the results of ${array[@]}. But first let's add a string to the array:

$ array[0]="a string"

Without the quotes:

$ printf "%s\n" ${array[@]}
a
string
1
3

With quotes:

$ printf "%s\n" "${array[@]}"
a string
1
3

Passing things around

Well you have 2 tactics that you can make use of within Bash. You can simply set variables so that they're globally scoped. This is often the technique that most people employ.

The other method involves passing by value, values to functions within Bash. I'll show a basic function where I pass it 2 values.

Example

$ function hello() {
 printf "I got arg1: %d and arg2: %d\n" $1 $2
}

Now when I execute it with different arguments:

$ hello 1 2
I got arg1: 1 and arg2: 2

$ hello 3 4
I got arg1: 3 and arg2: 4

$ hello 3 blah
bash: printf: blah: invalid number
I got arg1: 3 and arg2: 0

You can read more about arrays and functions within Bash here to get a better understanding of the technologies.

References

Share:
57,824

Related videos on Youtube

uxserx-bw
Author by

uxserx-bw

scrabbling to find ...... program exit 1

Updated on September 18, 2022

Comments

  • uxserx-bw
    uxserx-bw over 1 year

    I'm trying to figure out like three or four things at the same time.The most I need help with is how to get the greatest number in all the files that I have created on a prior run of my script, that created a new file with a (int) identifier. to separate all of the files that have no metadata, to single them out to keep all of them from being over written because as I'm storing them all in the same folder.

    One is now to I be sure that I am getting the correct value in the element, I'm only using one element, the first one [0] to update the file by incrementing it in order from 0 ..... infinity. The incrementing I figured out using.

    (( array[0]++ ))
    

    the part that confuses me the most is the syntax and how I have its value changed by the computer and not me manually. I need to figure out how to get the biggest number that was put in the last file the script stopped at when making them, then have it beginning that number+1 when I start it up again so that it does not start all over again with the value of zero only to over write the other files it created the last time I ran it.

    As one should know the value goes away when I shut the computer off which loses the variables value. instead of going in the file and looking just get a script to do it for me. this is what I have so far to try and figure out how to get the greatest number. it is the how do I be sure that I am writing it correctly for it to get that new number inside of the [0] element to start with the last number I left off at plus one?

    #!/bin/bash
    
    typeset -i xf mf sn bn hn n  snewnum d
    
    let xf=1 mf=0 bn=3 hn=4 n=1 snewnum=0
    
    #to keep track of which lost-song file number I am on
    n=0 bn=3 hn=4
    lostsongs[0]=2
    
    ###################################################
    #
    # FOR updating the lost song files so as not to 
    # over write any
    ####################################
    find /home/userx/testscripts/ -type f -name "*.mp3" | while [[ $n -le 4 ]] ; do
     read FILE;
    nstring=${FILE##*/} #gets just the file name
    lstring=${nstring##I*"("} #chops off Lside to the ( leaving num
    rstring=${lstring%%")"*} #chops off Rside to the ) leaving the num
    
    snewnum=$rstring #holds the char of type num 
    echo $snewnum " new num before if"
    
    lostsongs[n]="$snewnum"
    
    echo "lostsongs[$n] = ${lostsongs[n]}"
    
    echo ${#lostsongs[@]} " lostsongs length "
    
    for(( a=0; a<${#lostsongs[@]}-1 ;a++ )); 
        do
            store=0;
    
            if [[ lostsongs[a+1]<lostsongs[a] ]]; then
    
                store=lostsongs[a];
                lostsongs[a]=$lostsongs[a+1];
                lostsongs[a+1]=$store;
                echo "$store  in a"
            fi
    
    
        done
    
    
    
    let n++
    done
    

    The bigger problem I'm having to figure out, how to pass variables all over the script to everywhere I need it to go. As I need to get the old array[0] with the new value inside of it to the proper place to use it. Within a completely different while loop.

    find ~/music/ -type f -name "*.mp3" | while [ $xf  -le 150  ] ; 
      do read FILENAME;
       ...............................
    if [[ ! -n "$newArt" && ! -n "$newTit" && ! -n "$newAlb" ]] ; then
    
    echo "${lostsogns[0]} that is Lsogn num.. before going to sogn"
    newFile="I_HAVE_NO_IDEA-WHO-I-AM-(Lost-Song-Number-("${lostsongs[0]}"))-192k.mp3"
    (( lostsongs[0]++ ))
    let hn++
     ...............
    

    So I'd say my two major questions are how do I correctly write a re-assigning of an int value using a variable with a value inside of it into the array [ element ] other then incrementing or de-incrementing it by using the ++ or -- , and how do I pass it all around the script?

    why can't I seem to get

    array[0]=$newvalue 
    

    to work?

    Everything I've read always has this really big complected looking "what are they doing?" that is not even close to what I want to do examples that do nothing but confuse me more. I find it hard to fine the simple examples for me to learn from then grow from there in my programming.

  • Angel Todorov
    Angel Todorov over 10 years
    Much more robust to use the quoted "@"-form. To see the difference: a=("first element" "2nd elem"); printf "%s\n" ${a[@]}; printf "%s\n" "${a[@]}"
  • slm
    slm over 10 years
    @glennjackman - thanks for the tip, I'll incorporate it. I always forget the @ vs. *. The * makes more sense given it's often assoc. w/ wildcards as "everything". Let me know if I've got it right now.
  • Angel Todorov
    Angel Todorov over 10 years
    Yep that's it: unquoted, both @ and * expand to all the individual words in the array (split on $IFS); quoted, * expands to a single word (joined with $IFS); quoted, @ expands to each array element as a single word.