Umgebungsvariablen vs Positionsparameter
Bevor wir mit der Erörterung $INTEGERvon Variablentypen beginnen, müssen wir verstehen, was sie wirklich sind und wie sie sich von Umgebungsvariablen unterscheiden. Variablen, wie sie als $INTEGERPositionsparameter 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 $HOMEund $PATHUmgebungsvariablen. 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 Hellound Worldausgedruckt, da dies Positionsparameter für echodie Dinge sind, mit denen Sie arbeiten möchten echo. Und echoist 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 HelloundWorldliegt 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 HOMEoder PATHhaben ein bestimmtes Format, eine bestimmte Bedeutung und bedeuten für jedes Programm dasselbe. HOMEVariable bedeutet dasselbe für ein externes Dienstprogramm wie /usr/bin/findoder 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ücksichtigenUIDDie 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-terminalwann Blick auf Ihre gestartet SHELLUmgebungsvariable, 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 kshstatt bash. Dies ist auch ein Beispiel dafür, wie die Umgebung von Programmen verwendet wird. Wenn ich ausdrücklich sagen , gnome-terminalmit -ebestimmt 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- mainFunktion, die normalerweise so aussieht
int main(int argc, char **argv)
, wo argcist die Anzahl der Befehlszeilenargumente und argvist effektiv Array von Befehlszeilenparametern, und dann gibt es eine environFunktion (unter Linux man -e 7 environ), um auf Dinge wie den Home-Verzeichnispfad des Benutzers, eine Liste von Verzeichnissen zuzugreifen, in PATHdenen wir nach ausführbaren Dateien suchen können, usw. In ähnlicher Weise werden auch Shell-Skripte modelliert. In Schale Terminologie haben wir Positionsparameter $1, $2usw., 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 bashAnmeldeshell 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 -cOption nutzen können $1und $2Argumente. 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 -cOption 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 bashmit eigenen Positionsparametern gestartet haben , aber diese Positionsparameter wurden zu Parametern für echound stat. Und jedes Programm versteht es auf seine Weise. Wenn wir stateine Zeichenfolge angeben Hello Worldund keine Datei vorhanden Hello Worldist, wird ein Fehler ausgegeben. bashbehandelt es wie eine einfache Zeichenfolge, staterwartet jedoch, dass es sich bei dieser Zeichenfolge um einen vorhandenen Dateinamen handelt. Im Gegensatz dazu stimmen alle Programme darin überein, dass die Umgebungsvariable HOMEein 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=valueaus 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 shiftBefehl 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 setBefehl 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 setwerden 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 envund printenvbetrachten Befehle die tatsächliche Umgebungsvariable, mit der ein Befehl ausgeführt wird. Siehe auch das .
export 3drehen$3in eine Umgebungsvariable. Sie können nichtunset 3; und Sie können mit keinen$3neuen Wert zuweisen3=val.