Hozzon létre asszociatív tömböt két parancs kimenetéből

Felhasználói könyvtárakat próbálok létrehozni egy importált passwd fájl alapján, és megpróbálom betölteni az adatokat asszociatív tömb: tömb [felhasználónév] = könyvtár. Betölthetem a mezőket külön tömbökbe, de az asszociációkat nem tudom helyrehozni, mivel az egyes mezők az összes könyvtárhoz társulnak.

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 

Megjegyzések

  • Ha a meglévő válaszok bármelyike megoldja a problémát, kérjük, fontolja meg annak elfogadását a a pipa. Köszönöm!

Válasz

Az egészet közvetlenül a bash-val olvashatod, mondván az read-et kettőspontokra osztani :

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

Válasz

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

A awk szkript kimenetet készít [key]=val formátumban szükséges egy bash asszociatív tömb több elemének beállításakor, és duplán idézi mind a kulcsot, mind az értéket (["key"]="value"), ha a kulcsokban vagy az értékekben szóköz, tabulátor stb. .

A \n -t elválasztóként használtam, hogy megkönnyítsem, ha utólag szeretné feldolgozni a awk kimenet valamilyen más eszközzel (bár a awk amúgy a legtöbb dolgot megteheti, amit érdemes más eszközökkel megtenni).

Parancspótlás önmagában elégnek kell lennie .. .de az IMO miatt, ami egy hibát jelent a bash fájlban, ha a ( ... ) tömb definíciójában az első nem fehér szóköz karakter ” ta [, csak a must use subscript when assigning associative array hibaüzenetet generálja.

pl. a USERARRAY beállításának mindkét kísérlete sikertelen lesz:

 $ 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  

A megoldás hogy a kivonatolt tömb deklarálásakor a eval -t használja, mint a válaszom tetején található kód példában. Vagy

eval declare -A USERARRY=( $UA ) 

megjegyzések

  • 1. ez eval -t használja – természetesen ' veszélye van a parancs beinjekciózásának. Nem gondolom, hogy ebben az esetben ' probléma lenne, mert a válaszom az OP ' specifikus & feltehetően ellenőrzött / ismert-jó bemeneti fájl. 2. " elfelejtette idézni a bővítéseket " – mi? mit? Nem látok ' semmilyen idézőjeles problémát – az awk kód kifejezetten idézi mind a kulcsokat, mind a valsokat a tömbhöz. 3. A BTW, majdnem 2 évvel később, a bash v4.4.19 (1) kiadása még mindig nem ' t teszi lehetővé, hogy közvetlenül használjon cmd-subst, vagy akár a var egy hash deklarációban: declare -A array=( $(...) ) ugyanazzal a hibával bukik meg, így az eval továbbra is szükséges
  • @St é phaneChazelas Ha ' probléma merül fel, kérjük, magyarázza el, hogyan és miért – lehetőleg valós példa segítségével érvényes / etc / passwd stílusú bemenetet használva, ahogyan ez a kérdés és a válasz is releváns, nem csak általános és nyilvánvaló " ha szemétadatokat ad meg, ' kiszámíthatatlan és potenciálisan veszélyes eredményeket érhet el ".
  • Ön ' kapott egy pontot, amely általában nem okoz gondot a tipikus /etc/passwd adatok. Tehát hadd fogalmazzam meg újra: ⚠ bár a tipikus /etc/passwd adatoknál rendben kell lennie, ezt a megközelítést nem szabad önkényes adatokra használni, mivel ez parancsinjekciós sebezhetőséget jelent. Pontosabban azt feltételezi, hogy az adatok nem tartalmaznak ' t, `, ", visszavonást, $, *, ?, [, szóköz vagy NUL karakterek.
  • Az idézési problémáról lásd például a Biztonsági következményeket, ha elfelejtjük idézni a változó idézését a bash / POSIX héjakban és az ott összekapcsolt kérdések, hogy mit jelent a bővítések idézet nélkül hagyása.
  • Vegye figyelembe, hogy a bash régebbi verzióiban volt egy hiba, ahol ' a = (" $ x ") “nem sikerül létrehozni egy tömböt, amelynek egyik eleme a $x amikor $x valami [123]=qwe volt (ez a bash által támogatott asszociatív tömbök előtt volt).' igaz bash választhatta volna, hogy az asszociatív tömböket a=("$x") (ahol $x -nek [...]=) -vel kell kezdődnie a a=([$k]=$v) szintaxis mellett, de akkor meg kellett volna határoznia a módot billentyűk, amelyek] karaktereket tartalmaznak. Mindenesetre nem hibának, hanem tervezési döntésnek nevezném (itt a ksh hozta meg, ahonnan a bash átmásolta a szintaxisát).

Válasz

Két lista összevonása helyett a tömböt egyetlen ciklusban (és egyetlen hívást a awk címre a jó mérés érdekében) felépíthetjük egy lista visszaadásával. a user: dir bejegyzések száma, majd ezt felosztja változó bővítéssel:

#!/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 

Válasz

zsh hasznosabb, szokásosabb (hasonló a tcl vagy perl) az asszociatív tömbök egészének deklarálásának módja: array=(key1 value1 key2 value2...)

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

Megduplázódik \n, hasonlóan a ksh93 fájlhoz, eltávolítja az újsor speciális státuszát, mint IFS-szóköz karakter et. Enélkül a foo:\nbar:x “foo”, “bar”, “x” fel lett osztva a “foo”, “”, “bar”, “x” helyett.

A következővel: , a szintaxis ugyanolyan kínos, mint a ksh93 -ben: array=([key1]=value1 [key2]=value2), tehát nem tudja könnyen megszerezni a kimenetet parancsot egy asszociatív tömbbe, nem pedig egy hurok használatával, amely egyszerre egyetlen elem hozzárendelést hajt végre, ahogy mások megmutatták.

Ne feledje, hogy bash asszociatív tömbök ( szemben a ksh93 vagy a zsh) korlátozással rendelkezik, hogy a kulcs nem lehet üres karaktersorozat (itt nem kérdés). Egy másik korlátozás, amelyet ezúttal megosztottak az ksh93 vel, az, hogy sem a kulcs, sem az értékek nem tartalmazhatják a NUL bájtot (itt szintén nem kérdés).

(az asszociatív tömbök támogatása a ksh93-ban a kezdetektől (1993), hozzáadva a zsh -hez 1998-ban (3.1.5-pws-3) és a bash -hez 2009-ben ( 4.0))

Megjegyzések

  • Miért tetted fel a ' \ n ' kétszer az IFS-be?
  • @rubystallion lásd szerkesztés

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük