Separare spazi dei nomi per funzioni e variabili nelle shell POSIX


13

Nel trattino, le funzioni e le variabili sembrano vivere in spazi dei nomi separati:

fn(){
    fn="hello world"
}
fn; echo "The value is $fn!" #prints: The value is hello world!
fn; echo "The value is $fn!" #prints: The value is hello world!
#the fn variable doesn't conflict with the fn function

È una caratteristica specifica del trattino o una garanzia POSIX?


2
Il codice in realtà non dimostra che la fnfunzione si trova in uno spazio dei nomi separato; se eseguirlo una volta avesse cancellato la sua definizione, avremmo visto esattamente lo stesso comportamento. Dovresti mostrare che la funzione è ancora definita, ad es. Con type fndopo.
alexis

Risposte:


13

Una garanzia :

2.9.5 Comando di definizione della funzione

Una funzione è un nome definito dall'utente che viene utilizzato come semplice comando per chiamare un comando composto con nuovi parametri posizionali. Una funzione viene definita con un "comando di definizione della funzione". [...]

La funzione si chiama fname; l'applicazione deve garantire che sia un nome (vedere Nome XBD) e che non sia il nome di un'utilità integrata speciale. Un'implementazione può consentire altri caratteri in un nome di funzione come estensione. L'implementazione deve mantenere spazi dei nomi separati per funzioni e variabili.


Si noti inoltre che unsetha -ve -fscegliere tra annullare la variabile o la funzione con il nome dato. bash(al contrario della maggior parte delle altre shell) disattiverà la foo funzione con unset foose non ci sono foovariabili (!), un comportamento consentito da POSIX. Ecco perché negli script POSIX è buona norma utilizzare sempre uno -vo -f(e ovviamente anche negli bashscript, ma si noti che unsetpotrebbe non disinserire sempre una variabile bash, l' bashambito della variabile presenta alcuni problemi).
Stéphane Chazelas,

Si noti che nel bash pre-shellshock, si avrebbero problemi nell'esportazione della variabile e della funzione con un determinato nome, poiché bash finirebbe per usare lo stesso nome di variabile di ambiente per entrambi (inserendolo due volte nell'ambiente, alcuni comandi potrebbero rimuovere uno di loro)
Stéphane Chazelas il

8

Le variabili e le funzioni risiedono in diversi spazi dei nomi nel trattino e questo è anche specificato da POSIX :

L'implementazione deve mantenere spazi dei nomi separati per funzioni e variabili.

Inoltre, le variabili hanno portata globale, per impostazione predefinita. Alcune shell (ad esempio bash, ksh e zsh) forniscono la localparola chiave per dichiarare le variabili in una funzione solo con ambito locale.

Quindi, sì, il comportamento che stai riscontrando è garantito da POSIX.

POSIX non è standardizzato local , ma :

La descrizione delle funzioni in una proposta iniziale si basava sull'idea che le funzioni dovrebbero comportarsi come script di shell in miniatura; cioè, fatta eccezione per la condivisione delle variabili , la maggior parte degli elementi di un ambiente di esecuzione dovrebbe comportarsi come se fosse un nuovo ambiente di esecuzione, [..]

[..] Le variabili locali all'interno di una funzione sono state considerate e incluse in un'altra proposta iniziale (controllata dallo speciale incorporato local), ma sono state rimosse perché non si adattavano al modello semplice sviluppato per le funzioni e perché c'era ancora qualche opposizione all'aggiunta un altro nuovo built-in speciale che non faceva parte della pratica storica. Le implementazioni dovrebbero riservare l'identificatore local(nonché typeset, come usato in KornShell) nel caso in cui questo meccanismo di variabili locali venga adottato in una versione futura di questo standard.

(enfatizzare il mio)


ash (dalla fine degli anni '80) su cui si basa anche dash ha local, una delle interfacce più coerenti là fuori (rispetto a quella gravemente rotta in bash per esempio), bash solo di recente (4.4) ha preso in prestito il local -(per ambito locale per opzioni) da ash (implementando lo scoping in stile ash per quella sola $-variabile). ksh e yash non hanno local(solo le varianti di pdksh hanno local), ma typesetinvece (in ksh93 typesetfornisce l'ambito locale (statico) solo nelle funzioni dichiarate usando la sintassi ksh).
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.