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öketa=("$x")
(ahol$x
-nek[...]=
) -vel kell kezdődnie aa=([$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