Tout ce que dit titre. Je suis surpris par l’insuffisance des résultats de recherche Google pour cette question ! Ce que je veux est l’équivalent de dictionnaires Python mais en bash (et par conséquent, devrait fonctionner sur OSX, Ubuntu et autres distributions majeures de Linux).
Réponses
Trop de publicités?Bash 4
Bash 4 prend en charge cette fonctionnalité. Assurez-vous que votre script hashbang est - #!/usr/bin/env bash
ou #!/bin/bash
ou quoi que ce soit d'autre que des références bash
et pas sh
. Assurez-vous que vous êtes l'exécution de votre script, et ne pas faire quelque chose de stupide comme sh script
qui serait la cause de votre bash
hashbang pour être ignoré. C'est des trucs de base, mais autant garder à défaut, d'où la ré-itération.
Vous déclarez un tableau associatif en faisant:
declare -A animals
Vous pouvez le remplir avec des éléments à l'aide du tableau normal opérateur d'affectation:
animals=( ["moo"]="cow" ["woof"]="dog")
Ou les fusionner:
declare -A animals=( ["moo"]="cow" ["woof"]="dog")
Ensuite les utiliser comme des tableaux normaux. "${animals[@]}"
développe les valeurs, "${!animals[@]}"
(avis de l' !
) élargit les touches. N'oubliez pas de les citer:
echo "${animals["moo"]}"
for sound in "${!animals[@]}"; do echo "$sound - ${animals["$sound"]}"; done
Bash 3
Avant de bash 4, vous n'avez pas de tableaux associatifs. Ne pas utiliser eval
à les imiter. Vous devez éviter eval comme la peste, parce que c' est la peste de la création de scripts shell. La raison la plus importante est que vous ne voulez pas traiter vos données sous forme de code (il y en a beaucoup d'autres raisons aussi).
D'abord et avant tout: il suffit de considérer la mise à niveau vers bash 4. Sérieusement. L'avenir est maintenant, arrêtez de vivre dans le passé et qui en souffrent en forçant stupide cassé et laid hacks sur votre code et chaque pauvre âme coincé à l'entretenir.
Si vous avez quelques stupide excuse pourquoi vous "ne pouvez pas mettre à niveau", declare
est de loin la meilleure option. Il n'a pas d'évaluer les données que bash code comme celui - eval
, et comme tel, il ne pas permettre à un code arbitraire de l'injection assez facilement.
Nous allons préparer la réponse en introduisant les concepts:
Tout d'abord, l'indirection (sérieusement, n'utilisez jamais de cela, sauf si vous êtes des malades mentaux ou qui ont une autre mauvaise excuse pour l'écriture de hacks).
$ animals_moo=cow; sound=moo; i="animals_$sound"; echo "${!i}"
cow
Deuxièmement, declare
:
$ sound=moo; animal=cow; declare "animals_$sound=$animal"; echo "$animals_moo"
cow
Les réunir:
# Set a value:
declare "array_$index=$value"
# Get a value:
arrayGet() {
local array=$1 index=$2
local i="${array}_$index"
printf '%s' "${!i}"
}
Nous allons utiliser:
$ sound=moo
$ animal=cow
$ declare "animals_$sound=$animal"
$ arrayGet animals "$sound"
cow
Remarque: declare
ne peut pas être mis en fonction. Toute utilisation de l' declare
à l'intérieur d'un bash fonction transforme la variable elle crée des locaux à la portée de cette fonction, ce qui signifie que nous ne pouvons pas accéder ou de modifier les tableaux globaux. (En bash 4 vous pouvez utiliser déclarer g de déclarer des variables globales - mais en bash 4, vous devriez être en utilisant des tableaux associatifs en premier lieu, non pas ce hack.)
Résumé
La mise à niveau vers bash 4 et utiliser declare -A
. Si vous ne pouvez pas, envisager de passer entièrement à l' awk
avant de faire laid hacks comme décrit ci-dessus. Et certainement rester le diable loin de eval
hackery.
Vous pouvez encore modifier les hput()/hget() de l'interface de sorte que vous avez nommé les hachages comme suit:
hput() {
eval "$1""$2"='$3'
}
hget() {
eval echo '${'"$1$2"'#hash}'
}
et puis
hput capitals France Paris
hput capitals Netherlands Amsterdam
hput capitals Spain Madrid
echo `hget capitals France` and `hget capitals Netherlands` and `hget capitals Spain`
Cela vous permet de définir d'autres cartes qui ne sont pas en conflit (par exemple, 'rcapitals" qui n'pays recherche par ville capitale). Mais, de toute façon, je pense que vous trouverez que c'est assez terrible, en terme de performance.
Si vous voulez vraiment rapide hachage de recherche, il y a un terrible, terrible hack qui fonctionne vraiment bien. C'est cela: écrire vos clés/valeurs dans un fichier temporaire, un par ligne, puis utiliser " grep "^$touche" " pour les faire sortir à l'aide de tubes à couper ou awk ou sed ou que ce soit pour récupérer les valeurs.
Comme je l'ai dit, il a l'air terrible, et il semble que ça devrait être lente et de faire toutes sortes de inutiles IO, mais dans la pratique, il est très rapide (cache disque est génial, n'est-ce pas?), même pour les très grandes tables de hachage. Vous devez appliquer la clé de l'unicité de vous-même, etc. Même si vous n'avez que quelques centaines d'entrées, le fichier de sortie/grep combo va être un peu plus rapide - en mon expérience plusieurs fois plus rapide. Elle consomme également moins de mémoire.
Voici une façon de le faire:
hinit() {
rm -f /tmp/hashmap.$1
}
hput() {
echo "$2 $3" >> /tmp/hashmap.$1
}
hget() {
grep "^$2 " /tmp/hashmap.$1 | awk '{ print $2 };'
}
hinit capitals
hput capitals France Paris
hput capitals Netherlands Amsterdam
hput capitals Spain Madrid
echo `hget capitals France` and `hget capitals Netherlands` and `hget capitals Spain`