Píšu sadu funkcí shellu, které chci, aby fungovaly jak v Bash, tak v KornShell93, ale s Bash narážím na varování „kruhový název“.
Toto je podstata problému:
function set_it {
typeset -n var="$1"
var="hello:$var"
}
function call_it {
typeset -n var="$1"
set_it var
}
something="boff"
call_it something
echo "$something"
Spuštění:
$ ksh script.sh
hello:boff
$ bash script.sh
script.sh: line 4: warning: var: circular name reference
hello:
KornShell93 dělá přesně to, co chci, ale Bash selže a také varuje před stejnou věcí na řádku 2, pokud something
proměnná ve skriptu se jmenuje var
místo toho.
Chtěl bych mít var
proměnná být lokální pro každou funkci, proto používám typeset
, ale nezdá se, že by Bash rád „odkazoval“ nameref na proměnnou se stejným názvem jako samotný nameref. Nemohu použít local -n
nebo declare -n
protože by se zlomil v ksh
který je postrádá, a i kdybych to udělal, problém to neřeší.
Jediné řešení, které jsem našel, je použít v každé funkci jedinečné názvy proměnných , což vypadá poněkud hloupě, protože jsou místní.
Bash manuál říká následující o typeset
:
typeset
[…]
-n
Každému názvu dejtenameref
atribut, což z něj udělá
odkaz na jinou proměnnou. Tato další proměnná je
definována hodnotouname
. Všechny odkazy a
přiřazení kname
, kromě změny-n
samotný atribut, se provádějí na proměnné, na kterou odkazuje hodnota názvu.[…]
Při použití ve funkci
declare
atypeset
udělejte každý název
místní, jako ulocal
příkaz, pokud není-g
možnost je
dodávána. Pokud za názvem proměnné následuje=value
,
hodnota proměnné je nastavena navalue
.
Je zřejmé, že na Bashových odkazech na jména a funkčních lokálních proměnných je něco, čemu nerozumím.
Otázka tedy zní:Chybí mi v tomto případě něco o tom, jak Bash zachází s proměnnými reference názvu, nebo je to chyba/chybná funkce v Bash?
Aktualizovat :Momentálně pracuji s GNU bash, version 4.3.39(1)-release (x86_64-apple-darwin15)
stejně jako s GNU bash, version 4.3.46(1)-release (x86_64-unknown-openbsd6.0)
. Bash dodávaný s macOS je příliš starý na to, aby vůbec věděl o odkazech na názvy.
Aktualizovat :Ještě kratší:
function bug {
typeset -n var="$1"
printf "%sn" "$var"
}
var="hello"
bug var
Výsledky v bash: warning: var: circular name reference
. var
ve funkci by měla mít jiný rozsah z var
v celosvětovém měřítku. To ukládá volajícímu zbytečné omezení. Omezení zní:„nemáte povoleno pojmenovávat své proměnné, jak chcete, protože v této funkci může dojít ke střetu názvu s (místním) nameref.“
Přijatá odpověď:
Chet Ramey (správce Bash) říká
Na začátku tohoto roku proběhla rozsáhlá diskuse o namerefs na bug-bash. Mám rozumný návrh, jak toto chování změnit,
a po vydání bash-4.4 se na něj podívám.
Mezitím se uchyluji k mírnému zamlžení názvů mých lokálních proměnných nameref, aby se nekolidovaly v rámci knihovny ani (doufejme) s názvy globálních proměnných shellu.
V bash
5.0, toto je vždy tak trochu opraveno (ale ne ve skutečnosti opraveno). Toto je pozorované chování:
$ foo () { typeset -n var="$1"; echo "$var"; }
$ var=hello
$ foo var
bash: typeset: warning: var: circular name reference
bash: warning: var: circular name reference
bash: warning: var: circular name reference
hello
To ukazuje, že to funguje, ale je zde také několik varování.
Příslušný záznam NEWS říká
i. A nameref name resolution loop in a function now resolves to a variable by that name in the global scope.