Предотвратить выполнение подстановки команд при объявлении переменной

Ответ о расширении переменной ${+name}в основном решает проблему.

Я просто хочу добавить немного информации о сравнении скорости, чтобы завершить тему. Причина, по которой используется команда стиля (($+commands[tree])), заключается в том, что поиск команд в массиве выполняется быстрее, чем command -v tree, which -a tree.

❯ export TIMEFMT=$'%U user %S system %P cpu %*E total'

❯ time (for i ({1..100}) if (($+commands[tree])); then echo 1 &>/dev/null; fi)
0.00s user 0.00s system 89% cpu 0.006 total

❯ time (for i ({1..100}) if command -v tree &>/dev/null; then echo 1 &>/dev/null; fi)
0.00s user 0.00s system 95% cpu 0.010 total

❯ time (for i ({1..100}) if which -a tree &>/dev/null; then echo 1 &>/dev/null; fi)
0.01s user 0.01s system 97% cpu 0.021 total
2
23.03.2021, 14:49
1 ответ

Похоже, вам нужна переменная, содержимое которой генерируется динамически.

bashне поддерживает дисциплины ksh93 или динамический именованный каталог zsh или подстановку значений mksh , что упростило бы задачу, но вы могли бы используйте такой хак, используя namerefs:

var_generator() { date --iso-8601=ns; }
var_history=()
typeset -n var='var_history[
  ${##${var_history[${#var_history[@]}]=$(var_generator)}},${#var_history[@]}-1
]'

Здесь с var, определенным как ссылка на элемент массива $var_history, с использованием того факта, что индексы массива оцениваются динамически и позволяют запускать произвольный код (, здесь используется для запуска функции var_generatorи назначения его вывод в новый элемент массива ).

Тогда:

bash-5.1$ echo "$var"
2021-03-23T13:36:43,243211696+00:00
bash-5.1$ echo "$var"
2021-03-23T13:36:45,517726619+00:00

Это звучит слишком запутанно, хотя здесь можно просто использовать $(var_generator). Однако одно преимущество заключается в том, что вы все еще можете делать такие вещи, как ${var#pattern}, в то время как bash(, в отличие от zsh), не позволит вам делать ${$(cmd)#pattern}.

10
28.04.2021, 22:57

Теги

Похожие вопросы