Umgebungsvariablen vs Positionsparameter
Bevor wir mit der Erörterung $INTEGER
von Variablentypen beginnen, müssen wir verstehen, was sie wirklich sind und wie sie sich von Umgebungsvariablen unterscheiden. Variablen, wie sie als $INTEGER
Positionsparameter bezeichnet werden. Dies ist im POSIX-Standard (Portable Operating System Interface), Abschnitt 2.1 (Hervorhebung) beschrieben:
- Die Shell führt eine Funktion (siehe Befehl zur Funktionsdefinition), eine integrierte Datei (siehe Spezielle integrierte Dienstprogramme) oder ein Skript aus und gibt die Namen der Argumente als Positionsparameter mit den Nummern 1 bis n und den Namen des Befehls an (oder im Fall einer Funktion innerhalb eines Skripts der Name des Skripts) als Positionsparameter mit der Nummer 0 (siehe Befehlssuche und -ausführung).
Im Gegensatz dazu sind Variablen wie $HOME
und $PATH
Umgebungsvariablen. Ihre Definition ist in Abschnitt 8 der Norm beschrieben :
In diesem Kapitel definierte Umgebungsvariablen wirken sich auf den Betrieb mehrerer Dienstprogramme, Funktionen und Anwendungen aus. Es gibt andere Umgebungsvariablen, die nur für bestimmte Dienstprogramme von Interesse sind. Umgebungsvariablen, die nur für ein Dienstprogramm gelten, werden als Teil der Dienstprogrammbeschreibung definiert.
Beachten Sie deren Beschreibung. Positionsparameter sollen vor einem Befehl erscheinen, dh command positional_arg_1 positional_arg_2...
. Sie sollen vom Benutzer bereitgestellt werden, um dem Befehl mitzuteilen, was speziell zu tun ist. Wenn Sie dies tun echo 'Hello' 'World'
, werden die Zeichenfolgen Hello
und World
ausgedruckt, da dies Positionsparameter für echo
die Dinge sind, mit denen Sie arbeiten möchten echo
. Und echo
ist so aufgebaut, dass es Positionsparameter als zu druckende Zeichenfolgen versteht (es sei denn, sie sind eines der optionalen Flags wie -n
). Wenn Sie dies mit einem anderen Befehl tun, wird möglicherweise nicht verstanden, was Hello
undWorld
liegt daran, dass es vielleicht eine nummer erwartet. Beachten Sie, dass Positionsparameter nicht "geerbt" werden - ein untergeordneter Prozess kennt die Positionsparameter des übergeordneten Prozesses nur, wenn sie ausdrücklich an den untergeordneten Prozess übergeben werden. Häufig werden Positionsparameter mit Wrapper-Skripten übergeben. Diese prüfen möglicherweise, ob bereits ein Befehl vorhanden ist, oder fügen dem aufzurufenden realen Befehl zusätzliche Positionsparameter hinzu.
Im Gegensatz dazu sollen Umgebungsvariablen mehrere Programme beeinflussen. Sie sind Umgebungsvariablen , da sie außerhalb des Programms selbst festgelegt sind (mehr dazu weiter unten). Bestimmte Umgebungsvariablen wie HOME
oder PATH
haben ein bestimmtes Format, eine bestimmte Bedeutung und bedeuten für jedes Programm dasselbe. HOME
Variable bedeutet dasselbe für ein externes Dienstprogramm wie /usr/bin/find
oder Ihre Shell (und folglich für ein Skript) - es ist das Ausgangsverzeichnis des Benutzernamens, unter dem der Prozess ausgeführt wird. Beachten Sie, dass Umgebungsvariablen zum Beispiel verwendet werden können, um ein bestimmtes Befehlsverhalten zu berücksichtigenUID
Die Umgebungsvariable kann verwendet werden, um zu überprüfen, ob das Skript mit Root-Rechten ausgeführt wird oder nicht, und entsprechend zu bestimmten Aktionen zu verzweigen. Umgebungsvariablen sind vererbbar - untergeordnete Prozesse erhalten eine Kopie der übergeordneten Umgebung. Siehe auch Wenn Prozesse die Umgebung des übergeordneten Elements erben, warum müssen wir exportieren?
Kurz gesagt, der Hauptunterschied besteht darin, dass Umgebungsvariablen außerhalb des Befehls festgelegt werden und (normalerweise) nicht variiert werden sollen, während Positionsparameter Dinge sind, die vom Befehl verarbeitet werden sollen und sich ändern.
Nicht nur Shell-Konzepte
Was ich aus Kommentaren mitbekommen habe, ist, dass Sie Terminal und Shell vertauschen, und ich würde Ihnen wirklich empfehlen, über echte Terminals zu lesen , die früher physische Geräte waren. Heutzutage ist das "Terminal", auf das wir uns normalerweise beziehen, dieses Fenster mit schwarzem Hintergrund und grünem Text eigentlich Software, ein Prozess. Terminal ist ein Programm, das eine Shell ausführt, während Shell auch ein Programm ist, das jedoch das liest, was Sie eingeben, um es auszuführen (dh, wenn es sich um eine interaktive Shell handelt; nicht interaktive Shells sind Skripte und sh -c 'echo foo'
Arten von Aufrufen). Mehr zu Muscheln hier .
Dies ist eine wichtige Unterscheidung, aber auch wichtig zu erkennen, dass das Terminal ein Programm ist und daher dieselben Umgebungsregeln und Positionsparameter einhält. Ihre gnome-terminal
wann Blick auf Ihre gestartet SHELL
Umgebungsvariable, und laichen die entsprechende Standard - Shell für Sie, wenn Sie mit einem anderen Befehl angeben -e
. Sagen wir , ich meine Standard - Shell geändert ksh
- gnome-terminal wird dann laichen ksh
statt bash
. Dies ist auch ein Beispiel dafür, wie die Umgebung von Programmen verwendet wird. Wenn ich ausdrücklich sagen , gnome-terminal
mit -e
bestimmt Shell auszuführen - es wird es tun, aber es wird nicht dauerhaft sein. Im Gegensatz dazu soll die Umgebung größtenteils unverändert bleiben (dazu später mehr).
Wie Sie sehen können, sind Umgebungsvariablen und Positionsvariablen beide Eigenschaften eines Prozesses / Befehls und nicht nur eine Shell. Wenn es um Shell-Skripte geht, folgen sie auch dem Modell, das von der Programmiersprache C festgelegt wurde. Nehmen wir zum Beispiel die C- main
Funktion, die normalerweise so aussieht
int main(int argc, char **argv)
, wo argc
ist die Anzahl der Befehlszeilenargumente und argv
ist effektiv Array von Befehlszeilenparametern, und dann gibt es eine environ
Funktion (unter Linux man -e 7 environ
), um auf Dinge wie den Home-Verzeichnispfad des Benutzers, eine Liste von Verzeichnissen zuzugreifen, in PATH
denen wir nach ausführbaren Dateien suchen können, usw. In ähnlicher Weise werden auch Shell-Skripte modelliert. In Schale Terminologie haben wir Positionsparameter $1
, $2
usw., während die $#
Anzahl der Positionsparameter ist. Was ist $0
? Das ist der Name der ausführbaren Datei selbst, die ebenfalls aus der Programmiersprache C abgeleitet ist - argv[0]
wäre der Name Ihrer ausführbaren C-Datei. Dies gilt für die meisten Programmier- und Skriptsprachen .
Interaktive vs nicht interaktive Shells
Eines der Dinge, die ich bereits angedeutet habe, ist die Unterscheidung zwischen interaktiven und nicht interaktiven Shells . Die Eingabeaufforderung, in der Sie Befehle eingeben - das ist interaktiv, es interagiert mit dem Benutzer. Im Gegensatz dazu, wenn Sie ein Shell-Skript haben oder es bash -c''
nicht interaktiv ausführen .
Und hier wird Unterscheidung wichtig. Die Shell, die Sie bereits ausführen, ist ein Prozess, der mit Positionsparametern erzeugt wurde (für die bash
Anmeldeshell ist dies einer "... dessen erstes Zeichen des Arguments Null ein - ist oder einer, der mit der Option --login gestartet wurde" ( Referenz ). )
Im Gegensatz dazu Skripte und Muscheln mit ins Leben gerufen -c
Option nutzen können $1
und $2
Argumente. Zum Beispiel,
$ 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: -
Beachten Sie, dass ich dort auch verwendet habe sh
, weil eine kleine Eigenheit der -c
Option darin besteht, den ersten Positionsparameter zu nehmen und ihm zuzuweisen $0
, im Gegensatz dazu, dass es normalerweise ein Name des Programms ist.
Eine andere wichtige Sache ist, dass Positionsparameter das sind, was ich "framable" nenne. Beachten Sie, wie wir zuerst bash
mit eigenen Positionsparametern gestartet haben , aber diese Positionsparameter wurden zu Parametern für echo
und stat
. Und jedes Programm versteht es auf seine Weise. Wenn wir stat
eine Zeichenfolge angeben Hello World
und keine Datei vorhanden Hello World
ist, wird ein Fehler ausgegeben. bash
behandelt es wie eine einfache Zeichenfolge, stat
erwartet jedoch, dass es sich bei dieser Zeichenfolge um einen vorhandenen Dateinamen handelt. Im Gegensatz dazu stimmen alle Programme darin überein, dass die Umgebungsvariable HOME
ein Verzeichnis ist (es sei denn, der Programmierer hat es in unvernünftiger Weise codiert).
Können wir mit Umgebungsvariablen und Positionsparametern herumspielen?
Technisch können wir mit beiden herumspielen, aber wir sollten nicht mit Umgebungsvariablen herumspielen, während wir oft Positionsparameter bereitstellen müssen. Wir können Befehle in der Shell ausführen, indem wir eine Variable voranstellen, zum Beispiel:
$ hello=world bash -c 'echo $hello'
world
Wir können Variablen auch einfach export variable=value
aus der Shell oder dem Skript heraus in die Umgebung einfügen . Oder wir können einen Befehl mit völlig leerer Umgebung mit ausführen env -c command arg1 arg2
. In der Regel wird jedoch nicht empfohlen, mit der Umgebung herumzuspielen, insbesondere wenn Sie Variablen in Großbuchstaben verwenden oder bereits vorhandene Umgebungsvariablen überschreiben. Beachten Sie, dass dies empfohlen wird, obwohl dies kein Standard ist.
Bei Positionsparametern ist die Art und Weise der Einstellung offensichtlich. Stellen Sie sie einfach vor den Befehl, aber es gibt auch Möglichkeiten, sie auf andere Weise einzustellen und die Liste dieser Parameter über den shift
Befehl zu ändern .
Zusammenfassend ist der Zweck dieser beiden unterschiedlich, und sie existieren aus einem Grund. Ich hoffe, die Leute haben einen Einblick in diese Antwort erhalten, und es hat Spaß gemacht, sie so zu lesen, wie es für mich war, diese Antwort zu schreiben.
Hinweis zum Befehl set
Der set
Befehl verhält sich laut Handbuch wie folgt (aus Bash-Handbuch, Hervorhebung hinzugefügt):
Ohne Optionen werden der Name und der Wert jeder Shell-Variablen in einem Format angezeigt, das als Eingabe zum Festlegen oder Zurücksetzen der aktuell festgelegten Variablen verwendet werden kann.
Mit anderen Worten, es set
werden spezifische Variablen für die Shell betrachtet, von denen sich einige zum Beispiel zufällig in der Umgebung befinden HOME
. Im Gegensatz dazu mögen env
und printenv
betrachten Befehle die tatsächliche Umgebungsvariable, mit der ein Befehl ausgeführt wird. Siehe auch das .
export 3
drehen$3
in eine Umgebungsvariable. Sie können nichtunset 3
; und Sie können mit keinen$3
neuen Wert zuweisen3=val
.