Multi-dimensions des tableaux en Bash
Je suis la planification d'un script pour gérer certaines pièces de mon les systèmes Linux et je suis sur le point de décider si je veux utiliser les bash ou python.
Je préfère le faire comme un script Bash tout simplement parce que les commandes sont plus faciles, mais le vrai facteur décisif de la configuration. J'ai besoin d'être en mesure de stocker un tableau multidimensionnel dans le fichier de configuration pour indiquer au script de quoi faire avec lui-même. Stockage simple clé=valeur de paires dans des fichiers de configuration est assez simple avec bash, mais la seule façon que je peux penser à faire un tableau multidimensionnel est un deux couches de moteur d'analyse, quelque chose comme
array=&d1|v1;v2;v3&d2|v1;v2;v3
mais le marshall/unmarshall code pourrait arriver à être un ours, et sa loin d'être conviviale pour la prochaine pauvres sap qui a pour administrer ce. Si je ne peux pas le faire facilement en bash, je vais simplement écrire les configs à un fichier xml et d'écrire le script en python.
Est-il un moyen facile de le faire en bash?
merci à tous.
- Connexes: Comment déclarer tableau 2D en bash
Vous devez vous connecter pour publier un commentaire.
Bash ne prend pas en charge les tableaux multidimensionnels, ni de la cendre, et il semble que vous voulez une table de hachage que les valeurs sont des tableaux. Cette solution n'est pas très beau, une solution avec un fichier xml devrait être mieux :
declare -a "$elt"
au lieu deeval $elt
.Bash ne dispose pas d'un tableau multi-dimensionnel. Mais vous pouvez simuler un peu le même effet avec des tableaux associatifs. Voici un exemple de tableau associatif de faire semblant d'être utilisé comme un tableau multi-dimensionnel:
Si vous ne déclarez pas le tableau associatif (avec
-A
), le ci-dessus ne fonctionne pas. Par exemple, si vous omettez ledeclare -A arr
ligne, leecho
imprime2 3
au lieu de0 1
, parce que0,0
,1,0
et un tel sera pris comme une expression arithmétique et évalués à0
(la valeur à droite de l'opérateur virgule).C'est ce qui a fonctionné pour moi.
Il est basé sur cette réponse ici
NAME=${!MAIN_ARRAY[i]:0:1}
etVALUE=${!MAIN_ARRAY[i]:1:1}
si je ne me trompe pas, pour que cela fonctionne (c'est à dire. l'échangeURLS
pourMAIN
).Indépendant du shell utilisé (sh, ksh, bash, ...) ce qui suit est une approche qui fonctionne assez bien pour la n-dimensions des tableaux (l'échantillon couvre un tableau en 2 dimensions).
Dans l'exemple de la ligne de séparation (1ère dimension) est le caractère espace. Pour l'introduction d'un séparateur de champ (2ème dimension) le standard unix outil
tr
est utilisé. Supplémentaires séparateurs pour les dimensions supplémentaires peuvent être utilisés de la même manière.Bien sûr, la performance de cette approche n'est pas très bien, mais si la performance n'est pas un des critères de cette approche est assez générique et peut résoudre de nombreux problèmes:
La sortie de cet exemple ressemble à ceci:
Après beaucoup d'essais et d'erreurs, j'en fait de trouver la meilleure et la plus claire et la plus simple tableau multidimensionnel sur bash est l'utilisation régulière de la var. Yep.
Avantages: Vous n'avez pas à faire une boucle par un grand tableau, vous pouvez simplement echo "$var" et de l'utiliser grep/awk/sed. Il est clair et facile et vous pouvez avoir autant de colonnes que vous le souhaitez.
Exemple:
Si vous souhaitez trouver de tout le monde au pérou
Seulement grep(sed) dans le troisième champ
Si vous ne voulez champ x
Tout le monde au pérou que l'on appelle thomas et il suffit de retourner son nom
Toute requête que vous pouvez penser... supereasy.
Pour modifier un élément:
Pour supprimer une ligne qui contient "x"
Pour modifier un autre champ dans la même ligne basée sur une valeur à partir d'un autre point de
De cours de bouclage fonctionne aussi si vous voulez le faire
La seule gotcha iv e retrouve avec ceci est que vous doit toujours citer le
var(dans l'exemple; les var et j') ou les choses vont ressembler à ceci
et quelqu'un va sans doute dire qu'il ne fonctionne pas si vous avez de la place dans votre entrée, mais cela peut être résolu en utilisant une autre délimiteur dans votre entrée, par exemple, (à l'aide d'une utf8 char maintenant de souligner que vous pouvez choisir quelque chose de votre entrée ne contiennent pas, mais vous pouvez choisir ce que ofc):
Si vous souhaitez stocker des retours à la ligne dans votre entrée, vous pouvez convertir le retour à la ligne avant de l'entrée et de convertir de nouveau sur la sortie(ou n'utilisez pas de bash...). Profitez-en!
Expansion de Paul réponse - voici ma version de travail associatifs les sous-ensembles dans bash:
Il fonctionne avec un mélange de valeurs dans le tableau principal - chaînes/tableaux/assoc. les tableaux
La clé ici est d'envelopper le sous-tableaux simples citations et utilisation
*
au lieu de@
au moment d'enregistrer un subarray à l'intérieur du tableau principal et il serait donc stockés dans une seule et même chaîne séparée par des espaces:"${SUB_1[*]}"
Puis il le rend facile à analyser un tableau de que si la boucle à travers les valeurs avec
IFS=' ' read -a val <<< ${MAIN_ARRAY[$key]}
Le code ci-dessus sorties:
IFS=' ' read -a val <<< ${MAIN_ARRAY[$key]}
travail. Ce qui est IFS? Est-il une variable définis? Pourquoi lire est ajouté à la définition de la variable?IFS
– Une liste de caractères qui séparent les champs; utilisé lorsque la coquille se fend mots dans le cadre de l'expansion." 6.7 Tableaux: "Si le mot est entre guillemets,${name[*]}
se développe en un seul mot avec la valeur de chaque membre du groupe, séparés par le premier caractère de laIFS
variable, ...".Je le fais à l'aide de tableaux associatifs depuis bash 4 et réglage
IFS
à une valeur qui peut être définie manuellement.Le but de cette approche est d'avoir des tableaux de valeurs de tableau associatif clés.
Afin de définir des IFS par défaut juste unset il.
unset IFS
Ceci est un exemple:
La sortie du script ci-dessous est:
test=("x3:x4:x5")
lorsque vous faites référence à elle comme$test
: Vous pouvez simplement fairetest="x3:x4:x5"
.Je vous poste la suite, car il est très simple et claire de la pour imiter (au moins dans une certaine mesure, le comportement d'un tableau à deux dimensions dans Bash. Il utilise un ici-fichier (voir le manuel de Bash) et
read
(un Bash builtin commande):De sortie:
Physicist Wolfgang Pauli was born in 1900
Physicist Werner Heisenberg was born in 1901
Physicist Albert Einstein was born in 1879
Physicist Niels Bohr was born in 1885
La façon dont il fonctionne:
read
commande dans le manuel de Bash) séparer les éléments de ces vecteurs.read
de commande avec ses-a
option, on boucle sur chaque ligne du fichier (jusqu'à ce que nous atteignons la fin du fichier). Pour chaque ligne, nous pouvons attribuer les champs souhaités (= mots) à un tableau, qui nous a déclaré juste avant la boucle. Le-r
option pour leread
commande empêche les barres obliques inverses d'agir comme des caractères d'échappement, dans le cas où nous avons tapé des barres obliques inverses dans l'ici-documentphysicists.$$
.En conclusion, un fichier est créé comme un 2D-tableau, et ses éléments sont extraits à l'aide d'une boucle sur chaque ligne, et l'utilisation de la capacité de la
read
commande à assigner des mots pour les éléments d'un (indexée) tableau.Légère amélioration:
Dans le code ci-dessus, le fichier
physicists.$$
est donnée en entrée à lawhile
boucle, de sorte qu'il est en fait passé à laread
de commande. Toutefois, je trouve que cela pose des problèmes quand j'ai une autre commande de demander pour l'entrée à l'intérieur de lawhile
boucle. Par exemple, leselect
commande attend à l'entrée standard, et si elle est placée à l'intérieur de lawhile
de la boucle, il va prendre une entrée dephysicists.$$
, au lieu de les demander dans la ligne de commande pour la saisie de l'utilisateur.Pour corriger cela, j'utilise le
-u
option deread
, qui permet de lire à partir d'un descripteur de fichier. Nous n'avons qu'à créer un descripteur de fichier (avec leexec
commande) correspondant àphysicists.$$
et de le donner à la-u
option de lire, comme dans le code suivant:Avis que le descripteur de fichier est fermé à la fin.
J'ai un assez simple mais intelligente solution de contournement:
Il suffit de définir le tableau avec les variables en son nom. Par exemple:
Ne sais pas si cela aide, car il n'est pas exactement ce que vous avez demandé, mais cela fonctionne pour moi. (La même chose peut être réalisé simplement avec des variables sans le tableau)
Bash ne supporte tableau multidimensionnel, mais nous pouvons mettre en œuvre à l'aide d'Associer tableau. Ici, les indices sont la clé pour récupérer la valeur. Associer tableau est disponible dans
bash
version 4.Si vous souhaitez utiliser un script bash et le garder facile à lire vous recommandons de placer les données structurées, JSON, et ensuite utiliser léger outil jq dans votre commande bash pour parcourir le tableau. Par exemple avec le dataset suivant:
Vous pouvez parcourir ces données avec un script bash et jq comme ceci:
Sorties: