Créez un tableau associatif à partir de la sortie de deux commandes

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

  • @St é phaneChazelas Sil y a ‘ un problème de citation, veuillez expliquer comment et pourquoi – de préférence avec un exemple réel utilisant une entrée de style / etc / passwd valide, comme cela est pertinent pour cette question et réponse, pas seulement un  » générique et évident si vous alimentez des données inutiles, vous ‘ obtiendrez des résultats imprévisibles et potentiellement dangereux « .
  • Vous ‘ avez compris que ce ne serait généralement pas un problème pour /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.
  • À propos du problème de citation, voir par exemple Implications sur la sécurité de loubli de citer une variable dans les shells bash / POSIX et les questions qui y sont liées pour voir ce que signifie laisser les extensions sans guillemets.
  • Notez que les anciennes versions de bash avaient un bogue où ‘ a = ( » $ x « ) `ne parviendrait pas à créer un tableau avec un élément étant le contenu de $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

    Laisser un commentaire

    Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *