У меня есть сценарий bash, который использует jq
для поиска «зависимых» данных в некоторых JSON и принимает закрытие (найти зависимости зависимостей зависимостей и т. Д.).Scope issue memoising bash function with associative array
Это прекрасно работает, но может быть очень медленным, так как он может снова и снова находить одни и те же зависимости, поэтому я хотел бы его увековечить.
Я попытался использовать глобальный ассоциативный массив для сопоставления аргументов с результатами, но массив, похоже, ничего не хранит.
я извлек соответствующий код в следующей демо:
#!/usr/bin/env bash
# Associative arrays must be declared; use 'g' for global
declare -Ag MYCACHE
function expensive {
# Look up $1 in MYCACHE
if [ "${MYCACHE[$1]+_}" ]
then
echo "Using cached version" >> /dev/stderr
echo "${MYCACHE[$1]}"
return
fi
# Not found, perform expensive calculation
RESULT="foo"
echo "Caching result" >> /dev/stderr
MYCACHE["$1"]="$RESULT"
# Check if the result was cached
if [ "${MYCACHE[$1]+_}" ]
then
echo "Cached" >> /dev/stderr
else
abort "Didn't cache"
fi
# Done
echo "$RESULT"
}
function abort {
echo "$1" >> /dev/stderr
exit 1
}
# Run once, make sure result is "foo"
[[ "x$(expensive "hello")" = "xfoo" ]] ||
abort "Failed for hello"
# Run again, make sure "Using cached version" is in stderr
expensive "hello" 2>&1 > /dev/null | grep "Using cached version" ||
abort "Didn't use cache"
Вот мои результаты:
$ ./foo.sh
Caching result
Cached
Didn't use cache
Тот факт, мы получаем Cached
, кажется, указывает, что я храню и смотреть но они не сохраняются во всех ссылках expensive
, так как мы попали в ветвь Didn't use cache
.
Для меня это выглядит как предмет, возможно, вызванный declare
. Однако declare -A
, по-видимому, является требованием для использования ассоциативных массивов.
Вот моя версия Баша:
$ bash --version
GNU bash, version 4.3.42(1)-release (i686-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Как выяснить поведение я испытываю, я бы также оценить альтернативные пути функций memoising в Баше (желательно ничего, что прикасается к файловой системе, даже если это RAM на основе)
Ваша точка 3 кажется немного выключенной; вы переводите 'grep' в' дорогой', а не наоборот (он дает 'grep: (стандартный ввод): Ошибка ввода/вывода') – Warbo
Похоже на' [["x $ (...) "=" xfoo "]]' строка - это та, которая использует подпроцесс и, следовательно, не заполняет кеш. Линия 'grep' фактически работает как есть, если над ней помещен« дорогой »вызов, чтобы заполнить кеш. – Warbo
Правильно, я не читал оригинал достаточно близко. Труба выдалась мне больше, но '$ (...)' * также * работает 'дорогой' в подпроцессе. – chepner