Я думаю, что вам нужно отступить назад и подумать о том, что на самом деле представляет собой карта или ассоциативный массив. Все это - способ сохранить значение для данного ключа и быстро и эффективно вернуть это значение. Вы также можете захотеть перебирать ключи для получения каждой пары ключ-значение или удалять ключи и связанные с ними значения.
Теперь подумайте о структуре данных, которую вы все время используете в сценариях оболочки, и даже просто в оболочке без написания сценария, которая обладает этими свойствами. Тупик? Это файловая система.
Действительно, все, что вам нужно, чтобы иметь ассоциативный массив в программировании оболочки, это временный каталог. mktemp -d
является вашим конструктором ассоциативного массива:
prefix=$(basename -- "$0")
map=$(mktemp -dt ${prefix})
echo >${map}/key somevalue
value=$(cat ${map}/key)
Если вы не хотите использовать echo
и cat
, вы всегда можете написать несколько маленьких оберток; они смоделированы от Ирфана, хотя они просто выводят значение, а не задают произвольные переменные, такие как $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
edit : Этот подход на самом деле несколько быстрее, чем линейный поиск с использованием sed, предложенного спрашивающим, а также более надежен (он позволяет ключам и значениям содержать -, =, space, qnd ": SP:"). Тот факт, что он использует файловую систему, не делает ее медленной; эти файлы фактически никогда не гарантированно будут записаны на диск, если вы не вызовете sync
; для временных файлов, подобных этому, с коротким временем жизни, не исключено, что многие из них никогда не будут записаны на диск.
Я сделал несколько тестов кода Ирфана, модификации Джерри кода Ирфана и моего кода, используя следующую программу драйвера:
#!/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
Результаты:
$ 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