[bash] multidimensioneel array vullen vanuit file

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Guvner
  • Registratie: Oktober 2000
  • Laatst online: 05-04-2022
Hallo mede tweakers,

Ik heb een bestand met hierin de volgende regels:
tstsrv1 192.168.1.1
tstsrv2 192.168.1.2
tstsrv3 192.168.2.1
tstsrv4 192.168.2.2

Ik probeer in een bash script een bepaalde handeling uit te laten voeren op al deze servers. Dat is het probleem op zich niet zo.

Het probleem ontstaat op het moment dat ik de file wil gaan uitlezen naar een multidimensioneel array.

Ik wil graag de bovengenoemde data op verschillende punten laten terugkomen in het script. Op bepaalde momenten moet dit het ip zijn en andere momenten moet dit de hostname zijn.

Voor het gemak dacht ik gebruik te gaan maken van een mutidimensioneel array, zodat ik iets kan doen in de trend van:
.
Bash: mass-script.sh
1
2
echo array[0,0] wordt nu het script op gedaan.
ssh root@$array[0,1] /opt/testscript #of iets dergelijks


Mijn eigenlijke vragen zijn dus:
-hoe vul ik het bovenstaande bestand naar een multidimensioneel array.
-kan het zowieso wel wat ik wil?

Acties:
  • 0 Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Zover ik weet kan dat niet in bash. Maar je kunt wel 2 array's aanmaken. Je kunt ook +=2 doen in plaats van ++ en dan is, zodat je array er zo uit ziet:
0] tstsrv1
1] 192.168.1.1
2] tstsrv2
3] 192.168.1.2
4] tstsrv3
5] 192.168.2.1
6] tstsrv4
7] 192.168.2.2

Als je dan i+1 doet heb je het ip en i is het label.

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • grep
  • Registratie: Augustus 2001
  • Laatst online: 07-07 22:29

grep

meer begrep...

Multidimensioneel array kent bash inderdaad niet.

Zie hier wel iets, maar zie niet hoe dat bruikbaar is.

Misschien is het in dit geval nog het makkelijkste om de 2 gegevens in aparte arrays te zetten (wat ReenL ook suggereert geloof ik)?

host=("tstsrv1" "tstsrv2")
ip=("192.168.1.1" "192.168.1.2")

Corresponderende data is dan hetzelfde element in de arrays
${host[1]} heeft ${ip[1]}
${host[2]} heeft ${ip[2]}
etc.

[ Voor 6% gewijzigd door grep op 01-12-2011 10:10 ]

Specs | Outcast UT clan | You're going to reap what you sow.


Acties:
  • 0 Henk 'm!

  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 13:16

Super_ik

haklust!

voor multi dimensionale arrays gebruik ik altijd eval.

even snel een copy paste, die moet dus zelf even de \" fixen.
eval array_${X}_${Y}=\"X\"
eval ssh root@\"\$array_${X}_${Y}\"

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


Acties:
  • 0 Henk 'm!

  • Foeijonghaai
  • Registratie: Juli 2001
  • Laatst online: 31-08 19:57
uitlezen van meerder waarden op een regel gaat gemakkelijk met read (bash shell builtin)
code:
1
2
3
4
5
6
7
8
9
10
$ cat test.txt
1 aap
2 noot
3 mies

$ cat test.txt | while read i j; do echo $i "test" $j; done
1 test aap
2 test noot
3 test mies
test

[ Voor 13% gewijzigd door Foeijonghaai op 01-12-2011 13:57 . Reden: besef dat het meer ging om multidimensionale array dan om het uitlezen van meerdere vars ]


Acties:
  • 0 Henk 'm!

  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 13:16

Super_ik

haklust!

grootste ellende is dan wel dat variabelen buiten je lus niet meer beschikbaar zijn, omdat | een subshell aanmaakt.

code:
1
2
3
X=1
cat test.txt | while read i;do X=2; done
echo $X => geeft 1


om dit op te lossen moet je het zo doen:
code:
1
2
3
X=1
while read i; do X=2; done < test.txt
echo $X => geeft 2

[ Voor 28% gewijzigd door Super_ik op 01-12-2011 22:21 . Reden: hoe wel op te lossen voorbeeld erbij ]

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

kijk even naar
declare -a

ASSUME makes an ASS out of U and ME


Acties:
  • 0 Henk 'm!

  • Ertepeller
  • Registratie: November 2010
  • Laatst online: 12-09 15:05
Daarmee declareer je een één-dimensionaal array. Multi-dimensionale arrays kent bash niet.

"declare -a myArray" kun je ook schrijven als "myArray=()":
code:
1
2
3
4
5
$ myArray=()  # creeer een nieuw leeg array
$ myArray=(rood wit blauw)  # creeer + initialiseer
$ echo ${myArray[0]}  # Gebruik van individueel element; accolades zijn niet optioneel!
rood
$ myArray[3]=groen  # Assignment individueel element

In bovenstaand voorbeeld gaat het overigens om een integer-indexed array.

Er bestaat ook een associatieve variant (string-indexed):
code:
1
2
3
4
$ declare -A Kleur=([rood]=f00 [blauw]=00f)
$ echo ${Kleur[rood]}
f00
$ Kleur[groen]=0f0


Voor een uitgebreider verhaal en voorbeelden: http://wiki.bash-hackers.org/syntax/arrays

Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Kijk even naar de data die de TS aangeeft. Hij wil geen multidimensionele arrays. Ik had gehoopt dat iedereen het daar onderhand al over eens was...

Wil je dan toch een echte multidimensionele array, laat die data dan in de file staan en gebruik iets als:
Bash:
1
2
3
4
5
6
7
get_item() {
  local FILE="$1"
  local ROW="$2"
  local COL="$3"

  head -n "$ROW" "$FILE" | tail -n 1 | cut -f "$COL"
}

behoudens off-by-one errors. Als je even zoekt op internet zal je ook vinden dat de head/tail constructie nog iets efficienter kan met awk of sed. Als we dan toch bezig zijn met awk/sed:
Bash:
1
2
3
4
5
6
7
get_item() {
  local FILE="$1"
  local ROW="$2"
  local COL="$3"

  awk "NR==$ROW { print $COL; }" $FILE
}

(niet getest)

ASSUME makes an ASS out of U and ME

Pagina: 1