Variabili d'ambiente vs parametri posizionali
Prima di iniziare a discutere il $INTEGERtipo di variabili, dobbiamo capire cosa sono realmente e in che modo differiscono dalle variabili di ambiente. Variabili come i $INTEGERcosiddetti parametri posizionali. Questo è descritto nello standard POSIX (Portable Operating System Interface), sezione 2.1 (enfasi sulla miniera):
- La shell esegue una funzione (vedere Comando definizione funzione), integrata (vedi Utilità integrate speciali), file eseguibile o script, fornendo i nomi degli argomenti come parametri posizionali numerati da 1 a n e il nome del comando (o nel caso di una funzione all'interno di uno script, il nome dello script) come parametro posizionale numerato 0 (vedere Ricerca ed esecuzione dei comandi).
Al contrario, variabili come $HOMEe $PATHsono variabili di ambiente. La loro definizione è descritta nella sezione 8 della norma :
Le variabili d'ambiente definite in questo capitolo influiscono sul funzionamento di più utility, funzioni e applicazioni. Esistono altre variabili d'ambiente che interessano solo utilità specifiche. Le variabili d'ambiente che si applicano a una singola utility sono definite come parte della descrizione dell'utility.
Nota la loro descrizione. I parametri posizionali devono apparire davanti a un comando, ad es command positional_arg_1 positional_arg_2.... Sono pensati per essere forniti dall'utente per dire al comando cosa fare specificamente. Quando lo fai echo 'Hello' 'World', stamperà le stringhe Helloe World, perché questi sono parametri posizionali su echo- le cose su cui vuoi echooperare. Ed echoè costruito in modo tale da comprendere i parametri posizionali come stringhe da stampare (a meno che non siano uno dei flag opzionali come -n). Se lo fai con un comando diverso, potrebbe non capire cosa HelloeWorldè perché forse si aspetta un numero. Si noti che i parametri posizionali non sono "ereditati": un processo figlio non è a conoscenza dei parametri posizionali del genitore se non è passato esplicitamente al processo figlio. Spesso vedi che i parametri posizionali vengono passati con gli script wrapper - quelli che forse controllano l'istanza esistente di un comando o aggiungono ulteriori parametri posizionali al comando reale che verrà chiamato.
Al contrario, le variabili di ambiente sono destinate a influenzare più programmi. Sono variabili d' ambiente , perché sono impostate al di fuori del programma stesso (più su questo di seguito). Alcune variabili di ambiente come HOMEo PATHhanno un formato specifico, un significato specifico e significheranno lo stesso per ciascun programma. HOMELa variabile avrà lo stesso significato sia per l'utilità esterna che per /usr/bin/findla shell (e, di conseguenza, per uno script): è la directory home del nome utente in cui viene eseguito il processo. Si noti che le variabili ambientali possono essere utilizzate per tenere conto del comportamento specifico del comando, ad esempioUIDla variabile di ambiente può essere utilizzata per verificare se lo script viene eseguito con privilegi di root o meno e ramificare di conseguenza azioni specifiche. Le variabili di ambiente sono ereditabili: i processi figlio ottengono una copia dell'ambiente del genitore. Vedi anche Se i processi ereditano l'ambiente del genitore, perché dobbiamo esportare?
In breve, la distinzione principale è che le variabili di ambiente sono impostate al di fuori del comando e non sono pensate per essere variate (di solito), mentre i parametri posizionali sono cose che devono essere elaborate dal comando e cambiano.
Non solo concetti di shell
Quello che ho notato dai commenti è che stai mescolando terminali e shell, e ti consiglierei davvero di leggere su terminali reali che una volta erano dispositivi fisici. Al giorno d'oggi, il "terminale" a cui ci riferiamo in genere, quella finestra con sfondo nero e testo verde è in realtà un software, un processo. Terminal è un programma che esegue una shell, mentre shell è anche un programma ma quello che legge ciò che si digita per eseguire (ovvero, se si tratta di shell interattiva; le shell non interattive sono script e sh -c 'echo foo'tipi di invocazioni). Maggiori informazioni sulle conchiglie qui .
Questa è una distinzione importante, ma anche importante riconoscere che il terminale è un programma e quindi aderisce alle stesse regole di ambiente e parametri posizionali. Il tuo gnome-terminalquando avviato guarderà la tua SHELLvariabile di ambiente e genererà la shell predefinita appropriata per te, a meno che non specifichi qualche altro comando con -e. Diciamo che ho cambiato la mia shell predefinita in ksh - gnome-terminal verrà quindi generato kshinvece di bash. Questo è anche un esempio di come l'ambiente viene utilizzato dai programmi. Se io dico in modo esplicito gnome-terminalcon -eeseguire shell specifica - lo farà, ma non sarà permanente. Al contrario, l'ambiente dovrebbe essere per lo più inalterato (ne parleremo più avanti).
Come puoi vedere, le variabili di ambiente e di posizione sono entrambe proprietà di un processo / comando, non solo di shell. Quando si tratta di script di shell, seguono anche il modello impostato dal linguaggio di programmazione C. Prendiamo ad esempio la mainfunzione C che in genere sembra
int main(int argc, char **argv)
, dove argcc'è il numero di argomenti della riga di comando ed argvè effettivamente un array di parametri della riga di comando, e poi c'è la environfunzione (su Linux che è man -e 7 environ) di accedere a cose come il percorso della directory home dell'utente, l'elenco delle directory in PATHcui possiamo cercare eseguibili, ecc. Anche gli script di shell sono modellati in modo simile. Nella terminologia shell, abbiamo parametri posizionali $1, $2e così via, mentre $#certo numero di parametri posizionali. Che dire $0? Questo è il nome dell'eseguibile stesso, che è di nuovo modellato dal linguaggio di programmazione C - argv[0]sarebbe il nome del tuo "eseguibile". E questo è abbastanza vero per la maggior parte dei linguaggi di programmazione e scripting .
Shell interattive vs non interattive
Una delle cose che ho già accennato è la distinzione tra shell interattive e non interattive . Il prompt in cui si digitano i comandi: interattivo, interagisce con l'utente. Al contrario, quando si dispone di uno script di shell o si esegue bash -c''che non è interattivo.
Ed è qui che la distinzione diventa importante. La shell che si esegue già è un processo, che è stato generato con parametri posizionali (per la bashshell di login è uno "... il cui primo carattere dell'argomento zero è un -, o uno è iniziato con l'opzione --login." ( Riferimento ) )
Al contrario, gli script e le shell avviati con l' -copzione possono trarre vantaggio $1e $2argomenti. Per esempio,
$ bash -c 'echo $1; stat $2' sh 'Hello World' /etc/passwd
Hello World
File: '/etc/passwd'
Size: 2913 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 6035604 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2017-08-12 14:48:37.125879962 -0600
Modify: 2017-08-12 14:48:37.125879962 -0600
Change: 2017-08-12 14:48:37.137879811 -0600
Birth: -
Si noti che ho usato anche shlì, perché una piccola stranezza di -copzione è quella di prendere il primo parametro posizionale e assegnarlo, a $0differenza del solito essere un nome del programma.
Un'altra cosa che è importante notare è che i parametri posizionali sono quelli che io chiamo "framable". Notate come, inizialmente abbiamo lanciato bashi propri parametri posizionali, ma quei parametri posizionali sono diventati parametri a echoe stat. E ogni programma lo capisce a modo suo. Se dessimo statuna stringa Hello Worlde non ci fosse alcun file Hello World, si produrrebbe un errore; bashla tratta come una semplice stringa ma si stataspetta che quella stringa sia un nome file esistente. Al contrario, tutti i programmi concorderebbero sul fatto che la variabile d'ambiente HOMEè una directory (a meno che il programmatore non la abbia codificata in modo irragionevole).
Possiamo pasticciare con variabili d'ambiente e parametri posizionali?
Tecnicamente, possiamo fare confusione con entrambi, ma non dovremmo fare confusione con le variabili di ambiente, mentre spesso dobbiamo fornire parametri posizionali. Possiamo eseguire comandi in shell con anteporre una variabile, ad esempio:
$ hello=world bash -c 'echo $hello'
world
Possiamo anche posizionare le variabili nell'ambiente semplicemente usando export variable=valuedalla shell o dallo script. Oppure possiamo eseguire un comando con un ambiente completamente vuoto con env -c command arg1 arg2. Tuttavia, in genere non è consigliabile scherzare con l'ambiente, in particolare utilizzando variabili maiuscole o sovrascrivendo variabili di ambiente già esistenti. Si noti che è raccomandato sebbene non sia uno standard.
Per i parametri posizionali, il modo di impostarli è ovvio, basta anteporli al comando, ma ci sono anche modi per impostarli in altro modo , oltre a cambiare l'elenco di tali parametri tramite shiftcomando.
In conclusione, lo scopo di questi due è diverso ed esistono per un motivo. Spero che la gente abbia avuto un'idea di questa risposta, ed è stato divertente leggerlo come è stato per me scrivere questa risposta.
Nota sul comando set
Il setcomando, secondo il manuale, si comporta in questo modo (dal manuale di bash, enfasi aggiunta):
Senza opzioni, il nome e il valore di ciascuna variabile di shell vengono visualizzati in un formato che può essere riutilizzato come input per l'impostazione o il ripristino delle variabili attualmente impostate.
In altre parole, setesamina le variabili specifiche della shell, alcune delle quali si trovano nell'ambiente, ad esempio HOME. Al contrario i comandi gradiscono enve printenvosservano la variabile d'ambiente effettiva con cui viene eseguito un comando. Si veda anche questo .
export 3trasformarsi$3in una variabile di ambiente. Non puoiunset 3; e non puoi assegnare$3un nuovo valore usando3=val.