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 ilmoittamisena=("$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