Циркулярное имя

У меня есть этот script:

#!/bin/bash

function contains() {
  local -n array=$1
  local value=$2
  for item in "${array[@]}"; do
    [ "$item" = "$value" ] && return 0
  done
  return 1
}

array=(a "b c" "d")
value="b c"

contains array value

Запуск. Я получаю эту ошибку:

***: line 6: warning: array: circular name reference

Что это значит? Как это исправить?

Ответ 1

Сфокусируйтесь на первой строке функции contains:

local -n array=$1

Когда выполняется

contains array value

$1 устанавливается на array, поэтому команда local после расширений становится

local -n array=array

где круговая ссылка сразу очевидна.

Это известная проблема без идеального решения (см. "Проблема с bash ссылками на имя" в BashFAQ/048). Я бы предложил, что там предлагалось:

[T] здесь нет безопасного имени, которое мы можем дать для ссылки на имя. Если переменная вызывающего абонента имеет одно и то же имя, мы ввернуты.

...

Теперь, несмотря на эти недостатки, функция declare -n - это шаг в правильном направлении. Но вы должны быть осторожны, чтобы выбрать имя, которое вызывающий не будет использовать (что означает, что вам нужен какой-то контроль над вызывающим, если только сказать "не использовать переменные, начинающиеся с _my_pkg" ), и вы должны отклонить небезопасные входы.