1

I have this script who automatically add new values with a determined index o the array.

#!/bin/bash
declare -A DATA
DATA[sid0]='aaaa'
DATA[sid1]='bbbb'
DATA[sid2]='cccc'
function newserver {
    sidtotal=0
    indexcount=0
    for indexcount in "${!DATA[@]}"
    do
        if [[ $indexcount == sid* ]]
        then
            sidtotal=$((sidtotal+1))
        fi
    done
    read -p "Name: " id
    DATA["sid$((sidtotal))"]=$id
    echo ${DATA[@]}
    echo sidtotal= $sidtotal
    read -p "Would like do add more data? [y - n]" MOREDATA
}
newserver

while [ "$MOREDATA" == y ];do
    newserver
done

This script automatically add a new value on the data array on determined index....

I want to add the value id and the determined indexed array sidtotal but, i would like do add in to the script too, at the same moment when i add, the script.sh will add the line. Something like that.

.......

DATA[sid0]='aaaa'
DATA[sid1]='bbbb'
DATA[sid2]='cccc'
DATA[sid3]='newdata'

........

So when the script finish, the value will not disapear...

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55
  • 1
    Editing a running script can be tricky. Store the DATA in a different file for persistence instead. – choroba Jun 21 '23 at 20:58
  • Yes i know but, will be just a test. I want all the data be stayed in one file for secure. – Yohrannes Santos Bigoli Jun 21 '23 at 21:05
  • 1
    Yeah, don't edit a running script. I did it it once with `rm` in a script and it totally wiped out my entire home directory, don't be like me :-) – Jetchisel Jun 21 '23 at 21:06
  • do you know for a fact that you'll never have gaps in your indices, eg, you'll never *remove* an entry thus leaving you with `DATA[sid0]` and `DATA[sid2]`? in this scenario this piece of code - `DATA["sid$((sidtotal))"]=$id` - will see `sidtotal=2` and thus overwrite the current `DATA[sid2]` – markp-fuso Jun 21 '23 at 21:17
  • Yep.....thanks for explanation, yeah i will fix that later – Yohrannes Santos Bigoli Jun 21 '23 at 21:26

2 Answers2

0

Move the array definition into a separate file, and make your function overwrite it when adding a new element.

The following calls that file data.sh and assumes it starts out with

declare -A DATA=([sid0]="aaaa" [sid1]="bbbb" [sid2]="cccc")

as its contents.

#!/usr/bin/env bash

# The data array is defined in this file; source it.
. data.sh

newserver() {
    local sidtotal=0 indexcount=0
    for indexcount in "${!DATA[@]}"
    do
        if [[ $indexcount == sid* ]]; then
            sidtotal=$((sidtotal+1))
        fi
    done
    read -r -p "Name: " id
    DATA["sid$((sidtotal))"]=$id
    echo "${DATA[@]}"
    echo sidtotal= $sidtotal
    # Overwrite data.sh with the updated array definition
    declare -p DATA > data.sh
}


newserver
while true; do
    read -r -p "Would you like to add more data? [y - n] " MOREDATA
    if [ "$MOREDATA" == y ]; then
        newserver
    else
        break
    fi
done

Example usage:

$ bash demo.sh
Name: dddd
bbbb aaaa dddd cccc
sidtotal= 3
Would you like to add more data? [y - n] n
$ cat data.sh
declare -A DATA=([sid1]="bbbb" [sid0]="aaaa" [sid3]="dddd" [sid2]="cccc" )

Note a few other changes like fixing syntax errors, moving the prompt asking if you want to continue out of the function, and assorted other things to make shellcheck complain less about it.

Shawn
  • 47,241
  • 3
  • 26
  • 60
  • Thats soo good man, but i would like something more.. simple storate. Something like declare -p DATA >> scriptitself.sh i dont know.... I know thas not to be good idea but if you know a way too preserve the value whidout create a new file o will be gratefull – Yohrannes Santos Bigoli Jun 21 '23 at 21:22
  • @YohrannesSantosBigoli Modifying a file currently being executed by bash will break it quite badly. Storing the data in a separate file is superior in other ways too, like allowing you to have to multiple users each with their own, locking down its permissions and accessibility, easily reset things by just blanking the file, etc. – Shawn Jun 21 '23 at 21:32
  • Alright man, you guys changed my mind, I'll think about it..... – Yohrannes Santos Bigoli Jun 21 '23 at 21:40
0

As others have pointed out, what you are trying to do is probably not a good thing to do. However, it is not technically difficult to do. This minimally modified version of your code demonstrates one way to do it:

#!/bin/bash

function newserver {
    sidtotal=0
    indexcount=0
    for indexcount in "${!DATA[@]}"
    do
        if [[ $indexcount == sid* ]]
        then
            sidtotal=$((sidtotal+1))
        fi
    done
    read -p "Name: " id
    DATA["sid$((sidtotal))"]=$id
    echo ${DATA[@]}
    echo sidtotal= $sidtotal
    read -p "Would like do add more data? [y - n]" MOREDATA
}

# Read the program source lines into the 'prog_lines' array and eval the
# definition of the DATA associative array on the last line
readarray -t prog_lines <"${BASH_SOURCE[0]}"
eval "${prog_lines[-1]}"

newserver
while [ "$MOREDATA" == y ];do
    newserver
done

# Update the definition of DATA on the last line and rewrite the program file
prog_lines[-1]=$(declare -p DATA)
printf '%s\n' "${prog_lines[@]}" >"${BASH_SOURCE[0]}"

exit

declare -A DATA=([sid1]="bbbb" [sid0]="aaaa" [sid2]="cccc" )
  • The basic idea is to put the definition of DATA on the last line of the program file, read it at the start of the program, and update it at the end of the program.
  • Putting the modified definition at the end (after the final exit in the program) should avoid potential problems caused by the fact that Bash executes lines of code as it reads them from the source file. Changing a running Bash program can (and does, as I long ago learned the hard way) cause it to break in very strange, and potentially dangerous, ways.
  • Using eval is generally not a good idea. See Why should eval be avoided in Bash, and what should I use instead?. However, its use here is no worse than source data.bash (or . data.bash) because that is equivalent to eval "$(cat data.bash)". In all cases it's a problem only if the saved definition of DATA is bad.
  • The code requires at least Bash 4.1 (released in 2009) because it uses -1 as an index to access the last element in an array.
  • See Is it normal for printf '%s\n' "${array[@]}" to print one line per array element? for an explanation of the use of printf.
pjh
  • 6,388
  • 2
  • 16
  • 17