Je pense que vous devez prendre du recul et réfléchir à ce qu'est réellement une carte, ou un tableau associatif. Il s'agit simplement d'un moyen de stocker une valeur pour une clé donnée, et de récupérer cette valeur rapidement et efficacement. Vous pouvez également vouloir être capable d'itérer sur les clés pour récupérer chaque paire clé-valeur, ou supprimer les clés et leurs valeurs associées.
Maintenant, pensez à une structure de données que vous utilisez tout le temps en script shell, et même juste dans le shell sans écrire un script, qui a ces propriétés. Vous ne savez pas ? C'est le système de fichiers.
En réalité, tout ce dont vous avez besoin pour avoir un tableau associatif en programmation shell est un répertoire temporaire. mktemp -d
est votre constructeur de tableau associatif :
prefix=$(basename -- "$0")
map=$(mktemp -dt ${prefix})
echo >${map}/key somevalue
value=$(cat ${map}/key)
Si vous n'avez pas envie d'utiliser echo
y cat
vous pouvez toujours écrire de petits wrappers ; ceux-ci sont calqués sur ceux d'Irfan, bien qu'ils se contentent d'afficher la valeur au lieu de définir des variables arbitraires, comme par exemple $value
:
#!/bin/sh
prefix=$(basename -- "$0")
mapdir=$(mktemp -dt ${prefix})
trap 'rm -r ${mapdir}' EXIT
put() {
[ "$#" != 3 ] && exit 1
mapname=$1; key=$2; value=$3
[ -d "${mapdir}/${mapname}" ] || mkdir "${mapdir}/${mapname}"
echo $value >"${mapdir}/${mapname}/${key}"
}
get() {
[ "$#" != 2 ] && exit 1
mapname=$1; key=$2
cat "${mapdir}/${mapname}/${key}"
}
put "newMap" "name" "Irfan Zulfiqar"
put "newMap" "designation" "SSE"
put "newMap" "company" "My Own Company"
value=$(get "newMap" "company")
echo $value
value=$(get "newMap" "name")
echo $value
modifier : Cette approche est en fait assez rapide que la recherche linéaire utilisant sed suggérée par le questionneur, ainsi que plus robuste (elle permet aux clés et aux valeurs de contenir -, =, espace, qnd ":SP :"). Le fait qu'elle utilise le système de fichiers ne la rend pas lente ; ces fichiers ne sont en fait jamais garantis d'être écrits sur le disque à moins que vous n'appeliez sync
; pour les fichiers temporaires de ce type dont la durée de vie est courte, il n'est pas improbable que beaucoup d'entre eux ne soient jamais écrits sur le disque.
J'ai fait quelques benchmarks du code d'Irfan, de la modification du code d'Irfan par Jerry, et de mon code, en utilisant le programme pilote suivant :
#!/bin/sh
mapimpl=$1
numkeys=$2
numvals=$3
. ./${mapimpl}.sh #/ <- fix broken stack overflow syntax highlighting
for (( i = 0 ; $i < $numkeys ; i += 1 ))
do
for (( j = 0 ; $j < $numvals ; j += 1 ))
do
put "newMap" "key$i" "value$j"
get "newMap" "key$i"
done
done
Les résultats :
$ time ./driver.sh irfan 10 5
real 0m0.975s
user 0m0.280s
sys 0m0.691s
$ time ./driver.sh brian 10 5
real 0m0.226s
user 0m0.057s
sys 0m0.123s
$ time ./driver.sh jerry 10 5
real 0m0.706s
user 0m0.228s
sys 0m0.530s
$ time ./driver.sh irfan 100 5
real 0m10.633s
user 0m4.366s
sys 0m7.127s
$ time ./driver.sh brian 100 5
real 0m1.682s
user 0m0.546s
sys 0m1.082s
$ time ./driver.sh jerry 100 5
real 0m9.315s
user 0m4.565s
sys 0m5.446s
$ time ./driver.sh irfan 10 500
real 1m46.197s
user 0m44.869s
sys 1m12.282s
$ time ./driver.sh brian 10 500
real 0m16.003s
user 0m5.135s
sys 0m10.396s
$ time ./driver.sh jerry 10 500
real 1m24.414s
user 0m39.696s
sys 0m54.834s
$ time ./driver.sh irfan 1000 5
real 4m25.145s
user 3m17.286s
sys 1m21.490s
$ time ./driver.sh brian 1000 5
real 0m19.442s
user 0m5.287s
sys 0m10.751s
$ time ./driver.sh jerry 1000 5
real 5m29.136s
user 4m48.926s
sys 0m59.336s
2 votes
Voir aussi : Comment définir les tables de hachage en Bash ?