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[…]
-nKaždému názvu dejtenamerefatribut, 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
declareatypesetudělejte každý název
místní, jako ulocalpříkaz, pokud není-gmož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.