Luo assosiatiivinen taulukko kahden komennon tulosteesta.

Yritän luoda käyttäjähakemistoja tuodun passwd-tiedoston perusteella ja yritän ladata tiedot assosiatiivinen taulukko: array [käyttäjänimi] = hakemisto. Voin ladata kentät erillisiin matriiseihin, mutta en voi saada assosiaatioita oikein, koska kukin kenttä liitetään kaikkiin hakemistoihin.

USERLIST=$(cat /usrmkr/in.out | awk -F ":" "{print $1}") DIRLIST=$(cat /usrmkr/in.out | awk -F ":" "{print $6}") declare -A USERARRAY func_StoreData() { USERARRAY[$1]="$2" return $? } for ((u=0;u<${USERLIST[@]};u++)); do func_StoreData ${USERLIST[$u]} ${DIRLIST[$u]} done for i in ${!USERARRAY[@]}; do echo "making directory for $i in ${USERARRAY[$i]}" #Do stuff done 

Kommentit

  • Jos jokin olemassa olevista vastauksista ratkaisee ongelmasi, harkitse sen hyväksymistä valintamerkki. Kiitos!

Vastaa

Voisit lukea koko asian suoraan bashilla kertomalla lukea jakamaan kaksoispisteisiin :

declare -A userarray while IFS=: read -r username password uid gid gecos home shell; do userarray[$username]=$home done < /usrmkr/in.out 

vastaus

 eval declare -A USERARRAY=( $(awk -F: "{ printf "[\"%s\"]=\"%s\"\n", $1, $6}" /usrmkr/in.out) )  

Skripti awk tuottaa tuloksen muodossa [key]=val vaaditaan, kun asetetaan useita bash-assosiatiivisen taulukon elementtejä, ja lainauslaina sekä avain että arvo (["key"]="value"), jos näppäimissä tai arvoissa on välilyöntejä, sarkaimia jne. .

Olen käyttänyt \n erottimena, jotta se olisi helppoa, jos haluat jälkikäsitellä awk tuotos jollain muulla työkalulla (vaikka awk voi joka tapauksessa tehdä useimmat asiat, joita haluat ehkä tehdä muilla työkaluilla).

Komennon korvaaminen pitäisi olla itsessään riittävä .. .mutta IMO: n vuoksi virhe on bash, jos ( ... ) taulukon määritelmän ensimmäinen ei-välilyönnin merkki ei ole ” ta [, se tuottaa vain virheilmoituksen must use subscript when assigning associative array.

esim. molemmat seuraavista yrityksistä asettaa USERARRAY epäonnistuvat:

 $ bash --version | head -1 GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu) $ declare -A USERARRAY=($(awk -F: "{ printf "[\"%s\"]=\"%s\"\n", $1, $6}" /usrmkr/in.out)) bash: USERARRAY: $(awk -F: "{ printf "[\"%s\"]=\"%s\"\n", $1, $6}" /usrmkr/in.out): must use subscript when assigning associative array $ UA=$(awk -F: "{ printf "[\"%s\"]=\"%s\"\n", $1, $6}" /usrmkr/in.out) $ declare -A USERARRAY=( $UA ) bash: USERARRAY: $UA: must use subscript when assigning associative array  

Ratkaisu on käyttää eval hajautettua taulukkoa ilmoitettaessa, kuten vastauksen yläosassa olevassa koodiesimerkissä. Tai

eval declare -A USERARRY=( $UA ) 

kommentit

  • 1. tämä käyttää eval – tietysti ' on riski komento-injektoinnista. En kuitenkaan ' usko sen olevan ' ongelma tässä tapauksessa, koska vastaukseni on tarkoitettu käytettäväksi OP ' erityinen & oletettavasti tarkistettu / tunnettu-hyvä syötetiedosto. 2. " unohdin lainata laajennuksia " – vai? mitä? En näe ' mitään lainausongelmia – awk-koodi lainaa yksiselitteisesti taulukon sekä avaimet että venttiilit. 3. BTW, melkein 2 vuotta myöhemmin, bash v4.4.19 (1) -julkaisu ei edelleenkään ei ' anna sinun käyttää suoraan cmd-subst-tiedostoa tai jopa muuttuja hash-ilmoituksessa: declare -A array=( $(...) ) epäonnistuu samalla virheellä, joten eval vaaditaan edelleen
  • @St é phaneChazelas Jos ' on lainausongelma, selitä miten ja miksi – mieluiten reaalimaailman esimerkillä käyttämällä kelvollista / etc / passwd -tyyliä, kuten tämä kysymys ja vastaus on merkityksellinen, ei vain yleinen ja ilmeinen " jos syötät roskatietoja, saat ' ll arvaamattomia ja mahdollisesti vaarallisia tuloksia ".
  • Olet ' saanut pisteen, että se ei tyypillisesti ole ongelma tyypillisille /etc/passwd tiedot. Joten anna minun muotoilla se uudelleen: ⚠ vaikka sen pitäisi olla kunnossa tyypillisille /etc/passwd tiedoille, tätä lähestymistapaa ei pidä käyttää mielivaltaiseen dataan, koska se muodostaisi komennon injektio-ongelman. Erityisesti se olettaa, että tiedot eivät sisällä ' t, `, ", taaksepäin, $, *, ?, [, välilyönti tai NUL-merkkejä.
  • Tietoja lainausongelmasta on esimerkiksi Muuttujan lainaamisen unohtamisen bash / POSIX-kuoreissa turvallisuusvaikutukset ja siihen liittyvät kysymykset nähdäksesi, mitä tarkoittaa laajennusten jättäminen noteeraamattomiksi.
  • Huomaa, että bashin vanhemmissa versioissa oli vika, jossa ' a = (" $ x ") ”ei luoda taulukkoa, jossa yksi elementti on $x kun $x oli jotain [123]=qwe (joka oli ennen bashin tukemia assosiatiivisia taulukoita).Se ' tosi bash olisi voinut päättää sallia assosiatiivisten taulukoiden ilmoittamisen a=("$x") (missä $x on aloitettava [...]=) a=([$k]=$v) -syntaksin lisäksi, mutta sitten sen olisi pitänyt määritellä tapa määrittää näppäimet, jotka sisältävät] merkkiä. En missään tapauksessa kutsuisi sitä virheeksi vaan suunnittelupäätökseksi (tässä ksh: n tekemä, josta bash kopioi syntaksinsa).

Vastaa

Kahden luettelon yhdistämisen sijaan voimme rakentaa taulukon yhteen silmukkaan (ja yhden kutsun awk hyväksi) palauttamalla luettelon käyttäjä: dir-merkinnät jakamalla ne sitten muuttuvilla laajennuksilla:

#!/bin/bash declare -A USERARRAY for u in $(awk -F: "{print $1 ":" $6}" /usrmkr/in.out) do user=${u%:*} dir=${u#*:} USERARRAY[$user]=$dir done 

vastaus

zsh on hyödyllisempi, tavallisempi (samanlainen kuin tcl tai perl) tapa julistaa assosiatiiviset taulukot kokonaisuutena: array=(key1 value1 key2 value2...)

typeset -A userarray IFS=$":\n\n" userarray=($(cut -d : -f 1,6 < /usrmkr/in.out)) 

Kaksinkertaistaminen \n, kuten kohdassa ksh93, poistaa uuden rivin erityistilan IFS-välilyönninä . Ilman sitä foo:\nbar:x jaetaan osiin ”foo”, ”bar”, ”x” eikä ”foo”, ””, ”bar”, ”x”.

Kanssa , syntaksi on sama hankala kuin kohdassa ksh93: array=([key1]=value1 [key2]=value2), joten et voi helposti saada lähtöä komennon assosiatiiviseksi taulukoksi muulla tavalla kuin käyttämällä silmukkaa, joka suorittaa yhden yksittäisen elementin määrityksen kerrallaan, kuten muut ovat osoittaneet.

Huomaa, että bash assosiatiiviset taulukot ( toisin kuin ksh93 tai zsh), on rajoituksia siinä, että avain ei voi olla tyhjä merkkijono (ei asia tässä). Toinen rajoitus, joka jaetaan tällä kertaa ksh93 kanssa, on se, että avain tai arvot eivät voi sisältää NUL-tavua (ei myöskään asia tässä). ksh93: ssä alusta alkaen (1993), lisätty zsh -lehdelle vuonna 1998 (3.1.5-pws-3) ja bash vuonna 2009 ( 4.0))

Kommentit

  • Miksi asetit ' \ n ' kahdesti IFS: ään?
  • @rubystallion see edit

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *