Unterschied zwischen Erweiterung und Substitution in der Shell-Scripting-Terminologie

8

Expansion und Substitution scheinen in der Shell-Programmiersprache im selben Kontext austauschbar zu sein. In einigen Dokumenten wie dem Bash-Referenzhandbuch und dem Bash Hackers Wiki wird beispielsweise das Wort "Erweiterung" verwendet, um die " Erweiterung der Shell-Parameter" zu erklären . Einige andere Dokumente scheinen jedoch das Wort "Substitution" zu bevorzugen. Erweiterte Bash-Scripting Guide verwendet Parameter substituion .

Gibt es einen Unterschied zwischen "Erweiterung" und "Substitution" in Bezug auf die Terminologie der Shell-Programmierung?

MS.Kim
quelle
Beide gelten in unterschiedlichen Kontexten, zum Beispiel variable expansion, command substitution. Was ist dein Zweifel?
devnull
Ohne spezifischen Kontext befürchte ich, dass dies zu weit gefasst und auch unklar ist.
devnull
Auf der Bash-Manpage scheint im Allgemeinen das Wort "Erweiterung" verwendet zu werden, wenn nur Shell-interne Inhalte beteiligt sind, während "Substitution" für Dinge bevorzugt wird, die externe Prozesse betreffen.
Celtschk
Wenn Sie meinen Rat befolgen , hören Sie auf, diese Dokumente zu lesen, bis Sie mit diesen vollständig vertraut sind: pubs.opengroup.org/onlinepubs/9699919799/utilities/… Wenn Sie mit denen fertig sind, die Sie tun man shund man set. Und wenn Sie das Zeug erledigt haben, dann machen Sie die Shell-spezifischen Dokumente.
Mikesserv
@devnull Du hast recht. Obwohl ich den Link für den Kontext eingefügt habe, ist es besser, den Kontext explizit mit Fragen anzugeben. Ich werde die Frage so bearbeiten, dass die Leute sie klar verstehen können.
MS.Kim

Antworten:

6

Substitution ist in diesem Zusammenhang fast gleichbedeutend mit Expansion, da sich ihre Bedeutungen überschneiden. Keiner von beiden ist eine vollständige Unterkategorie des anderen, obwohl es im Abschnitt zum GNU-Handbuch, auf den Sie verweisen, Substitutionen gibt, die als Teil einer Gesamterweiterung betrachtet werden.

Eine Erweiterung extrahiert den Wert eines Bezeichners. ZB wenn this=that, wenn wir expandieren this, bekommen wir that. Eine Erweiterung, die keine Substitution beinhaltet, ist insofern vorbestimmt, als der verwendete Wert bereits vorhanden ist und einfach abgerufen werden muss, obwohl dies das Kombinieren von abgerufenen / expliziten Werten umfasst (z. B. mit "arithmetischer Erweiterung").

Eine Ersetzung erzeugt einen Wert als Ergebnis einer expliziten Eingabe- / Ausgabeoperation. ZB wenn this=$(foo bar), thisist das Ergebnis der Ausführung foo barund seine Ausgabe zu erfassen. 1 Obwohl der Wert, der sich aus einer Substitution ergibt, möglicherweise vollständig vorhersehbar ist, unterscheidet er sich von dem Wert, der bei einer normalen Erweiterung abgerufen wird, da er erst dann existiert, wenn die Substitution stattfindet - er wird erzeugt.

Substitutionen gibt es in zwei Varianten, Befehl und Prozess , die irgendwie symmetrisch sind:

# Command substitution
foo=$(ls)
# Process substitution
wc <(ls)

Der "Befehl" im ersten ist ls, ebenso wie der "Prozess" im zweiten. Wir könnten sagen, was ersetzt wird, ist wirklich das Ende einer Pfeife. Die Prozessersetzung überschneidet sich mit der Umleitung . Dies ist jedoch wahrscheinlich technisch etwas zu restriktiv, was uns zur Fußnote bringt ...


  1. foo barIn diesem Fall kann es sich um eine interne Shell-Funktion handeln. In diesem Fall gibt es keine Interprozess-E / A. Die Existenz von Shell-Einbauten verdeckt diesen Unterschied weniger offensichtlich. Inhaltlich sind Eingabe und Ausgabe gleich.
Goldlöckchen
quelle
Ich mag diese Erklärung, aber wie würde man sie mit der Dateinamenerweiterung quadrieren , die sicherlich eine Reihe von Dateinamen als Ergebnis einer Operation erzeugt (ein Matching-Algorithmus).
De Novo
Sicher, aber um Semantik zu spielen, ist "Extrahieren des Werts eines Bezeichners" (was ich als Erweiterung bezeichnet habe) nicht auch eine Operation, also eine Substitution? Zumal "es Substitutionen gibt, die als Teil einer Gesamterweiterung betrachtet werden". Das heißt, die Beziehung zwischen diesen Wörtern ist nicht analog zur Unterscheidung zwischen links und rechts. Ich denke, die Dateinamenerweiterung passt gut zu meiner ursprünglichen Definition der Erweiterung, aber ich habe die obigen Informationen zu Substitutionen geklärt, um klarer zu machen, warum dies nicht der Fall ist.
Goldlöckchen
Das Problem, das ich beim Quadrieren dieser ansonsten intuitiven Erklärung mit der Dateinamenerweiterung hatte, war nicht, dass ich wollte, dass die Begriffe ausschließlich definiert werden, aber dass die Dateinamenerweiterung nicht den Wert abruft, der an einen Bezeichner gebunden ist. Innerhalb einer bestimmten Shell hängt der Wert für einen bestimmten Glob von mehr als nur dem Glob ab, und derselbe Glob kann in verschiedenen Kontexten unterschiedliche Ausgaben erzeugen. Außerdem muss der Wert nicht gebunden werden, um ihn später abzurufen. Die Beziehung ist nicht willkürlich (wie in foo = "was auch immer Sie möchten"; Echo "$ foo"), sondern Berechnung und Ergebnis.
De Novo
Ich nehme an, die Beziehung zwischen Ausdruck und Wert in der arithmetischen Erweiterung ist auch nicht (genau) willkürlich, aber es gibt definitiv nur einen Wert für eine bestimmte Erweiterung, unabhängig vom Kontext. Ich mag hier nur pingelig sein, aber von allen Shell-Erweiterungen scheint die Dateinamenerweiterung angesichts dieser Erklärung der seltsame Mann zu sein.
De Novo
2
set -- arg arg2
echo ${2+"$1"}
 #OUTPUT 
arg

shift
echo ${2+"$1"}
 #OUTPUT

 #there doesn't seem to be anything here

Ich denke, der Unterschied ist im Allgemeinen zu gering, um beachtet zu werden - und die Begriffe werden oft synonym verwendet. Obwohl, wenn man sich den beiden oben genannten Fälle anschaut, kann man das im ersten Beispiel sehen wir Ersatz $1 für $2als Folge der Expansion von $2. Sobald $2nicht erweitert werden kann, erfolgt keine Substitution.

Goldlöckchen machen einen guten Punkt über die ätherische Existenz von Substitutionen. Ein bisschen wie Schrödingers Katze, denke ich. Es erinnerte mich an etwas. Sie sind möglicherweise nicht mit dieser Form der von POSIX angegebenen Parametererweiterung vertraut, sie funktioniert jedoch in umgekehrter Weise wie oben beschrieben:

${var:?if $var is unset or null its \
     parent shell dies and this message is output to stderr}

Jetzt möchte ich manchmal das gleiche Verhalten, aber für einen setWert. POSIX gibt dieses Verhalten für nichts genau an. Aber mit ein oder zwei Tricks ist es einfach gelungen:

N= #N is null
var="any value should fail"
${var:+${N:?we substitute our \$Null var when \$var is expanded}}
  #OUTPUT
sh: line 3: N: we substitute our $Null var when $var is expanded

Aber:

N= #N is null
var=
${var:+${N:?is never substituted}}
  #OUTPUT

#there doesn't seem to be anything here
mikeserv
quelle