Jessaie de créer des répertoires dutilisateurs basés sur un fichier passwd importé et jessaie de charger les données dans un tableau associatif: tableau [nom dutilisateur] = répertoire. Je peux charger les champs dans des tableaux séparés mais je ne peux pas obtenir les associations correctes, car chaque champ est associé à tous les répertoires.
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
Commentaires
- Si lune des réponses existantes résout votre problème, veuillez envisager de laccepter via la coche. Merci!
Réponse
Vous pouvez lire le tout avec bash directement, en disant read pour diviser sur les deux-points :
declare -A userarray while IFS=: read -r username password uid gid gecos home shell; do userarray[$username]=$home done < /usrmkr/in.out
Réponse
eval declare -A USERARRAY=( $(awk -F: "{ printf "[\"%s\"]=\"%s\"\n", $1, $6}" /usrmkr/in.out) )
Le script awk
produit une sortie au format [key]=val
requis lors de la définition de plusieurs éléments dun tableau associatif bash, et des guillemets doubles à la fois la clé et la valeur (["key"]="value"
) au cas où il y aurait des espaces, des tabulations, etc. dans les clés ou les valeurs .
Jai « utilisé \n
comme séparateur pour vous faciliter la tâche au cas où vous souhaiteriez post-traiter le awk
sortie avec un autre outil (bien que awk
puisse faire la plupart des choses que vous pourriez vouloir faire avec dautres outils, de toute façon).
Substitution de commande devrait suffire à lui seul. .mais à cause de ce qui est, IMO, un bogue dans bash
, si le premier caractère autre quun espace blanc dans la définition du tableau ( ... )
nest » ta [
, il produit juste le message derreur must use subscript when assigning associative array
.
par exemple les deux tentatives suivantes pour définir USERARRAY échoueront:
$ 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
La solution est utiliser eval
lors de la déclaration du tableau haché, comme dans lexemple de code en haut de ma réponse. Ou,
eval declare -A USERARRY=( $UA )
Commentaires
- 1. cela utilise
eval
– bien sûr il y a ‘ un risque dinjection de commandes. Je ne ‘ Je ne pense pas que ‘ est un problème dans ce cas, cependant, car ma réponse est destinée à être utilisée avec lOP ‘ & spécifique à
fichier dentrée vraisemblablement vérifié / en bon état. 2. « jai oublié de citer les extensions » – hein? quelle? Je ne vois ‘ aucun problème de citation – le code awk cite explicitement les clés et les valeurs du tableau. 3. BTW, près de 2 ans plus tard, bash v4.4.19 (1) -release toujours ne ‘ t vous permet dutiliser directement un cmd-subst ou même une variable dans une déclaration de hachage:declare -A array=( $(...) )
échoue avec la même erreur, donc eval est toujours nécessaire
/etc/passwd
données. Alors permettez-moi de reformuler: ⚠ alors que cela devrait être OK pour les données /etc/passwd
typiques, cette approche ne devrait pas être utilisée pour des données arbitraires car elle constituerait une vulnérabilité dinjection de commandes. Plus précisément, il suppose que les données ne contiennent ‘, `
, "
, aucune barre oblique inverse, $
, *
, ?
, [
, tabulation despace ou caractères NUL. $x
quand $x
était quelque chose comme [123]=qwe
(cétait avant que bash ne prenne en charge les tableaux associatifs).Le vrai bash de ‘ aurait pu choisir de permettre aux tableaux associatifs dêtre déclarés comme a=("$x")
(où $x
doit commencer par [...]=
) en plus de la syntaxe a=([$k]=$v)
mais ensuite, il aurait fallu définir un moyen de spécifier clés contenant] caractères. Dans tous les cas, je nappellerais pas cela un bogue mais une décision de conception (ici prise par ksh doù bash a copié sa syntaxe). Réponse
Plutôt que de fusionner deux listes, nous pouvons construire le tableau en une seule boucle (et un seul appel à awk
pour faire bonne mesure) en renvoyant une liste des entrées user: dir puis en les divisant par des extensions de variables:
#!/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
Answer
zsh
a un plus utile, plus habituel (similaire à tcl
ou perl
) manière de déclarer les tableaux associatifs dans leur ensemble: array=(key1 value1 key2 value2...)
typeset -A userarray IFS=$":\n\n" userarray=($(cut -d : -f 1,6 < /usrmkr/in.out))
Doublage \n
, comme dans ksh93
supprime le statut spécial du saut de ligne en tant que caractère IFS-espace . Sans lui, foo:\nbar:x
serait divisé en « foo », « bar », « x » au lieu de « foo », « », « bar », « x ».
Avec , la syntaxe est la même maladroite que dans ksh93
: array=([key1]=value1 [key2]=value2)
, vous ne pouvez donc pas obtenir facilement la sortie dune commande dans un tableau associatif autrement quen utilisant une boucle effectuant une seule affectation délément à la fois comme dautres lont montré.
Notez que bash
tableaux associatifs ( contrairement à ksh93
ou zsh
) ont une limitation en ce que la clé ne peut pas être la chaîne vide (ce nest pas un problème ici). Une autre limitation, cette fois partagée avec ksh93
est que ni la clé ni les valeurs ne peuvent contenir loctet NUL (ce nest pas non plus un problème ici).
(la prise en charge des tableaux associatifs était dans ksh93 depuis le début (1993), ajouté à zsh
en 1998 (3.1.5-pws-3) et bash
en 2009 ( 4.0))
Commentaires
- Pourquoi avez-vous mis ‘ \ n ‘ deux fois dans lIFS?
- @rubystallion voir modifier