Mir ist klar, dass dies !
im Kontext des Befehlszeilenverlaufs eine besondere Bedeutung für die Befehlszeile hat, aber abgesehen davon kann das Ausrufezeichen in einem ausgeführten Skript manchmal einen Parsing-Fehler verursachen.
Ich denke, es hat etwas mit einer zu tun event
, aber ich habe keine Ahnung, was eine Veranstaltung ist oder was sie tut. Trotzdem kann sich ein Befehl in verschiedenen Situationen unterschiedlich verhalten.
Das letzte Beispiel unten verursacht einen Fehler. aber warum, wenn derselbe Code außerhalb der Befehlsersetzung funktioniert hat? .. mit GNU bash 4.1.5
# This works, with or without a space between ! and p
{ echo -e "foo\nbar" | sed -nre '/foo/! p'
echo -e "foo\nbar" | sed -nre '/foo/!p'; }
# bar
# bar
# This works, works when there is a space between ! and p
var="$(echo -e "foo\nbar" | sed -nre '/foo/! p')"; echo "$var"
# bar
# This causes an ERROR, with NO space between ! and p
var="$(echo -e "foo\nbar" | sed -nre '/foo/!p')"; echo "$var"
# bash: !p': event not found
bash
command-history
quoting
Peter.O
quelle
quelle
protected
Wäre angemessener gewesen. (geschützt durch einfache Anführungszeichen)var=$(…)
(keine doppelten Anführungszeichen) verwenden, und es wird so funktionieren, wie Sie es erwarten (glaube ich). Dies ist immer noch „sicher“ , weil der Wert Teil einer einfache Zuordnung ist nicht Gegenstand Wort Spaltung oder Globbing (obwohl dies nicht die Zuordnungen wahr sein kann durch builtins erfolgen (zBexport
,local
usw.) unter allen Schalen). Leider geht dies nicht über einfache Zuweisungen hinaus, da die doppelten Anführungszeichen den Schutz vor Worttrennung und Globbing bieten und andere Arten der Erweiterung in anderen Kontexten ermöglichen.Antworten:
Der
!
Charakter ruft die Ersetzung der Bash-Historie auf. Nach einer Zeichenfolge (wie in Ihrem fehlerhaften Beispiel) wird versucht, auf das letzte Verlaufsereignis zu expandieren, das mit dieser Zeichenfolge begonnen hat. So wie es$var
auf den Wert dieser Zeichenfolge!echo
erweitert wird, wird es auf den letzten Echo-Befehl in Ihrem Verlauf erweitert.Der Weltraum ist in solchen Erweiterungen ein brechender Charakter. Beachten Sie zunächst, wie dies mit Variablen funktionieren würde:
Dasselbe wird für die Erweiterung der Geschichte passieren. Das Bang-Zeichen (
!
) beginnt mit einer History-Ersetzungssequenz, jedoch nur, wenn eine Zeichenfolge folgt. Wenn Sie ein Leerzeichen darauf setzen, wird es buchstäblich als Teil einer Ersetzungssequenz ausgegeben.Sie können diese Art des Ersetzens sowohl für Variablen als auch für Verlaufserweiterungen vermeiden, indem Sie einfache Anführungszeichen verwenden. Ihre ersten Beispiele verwendeten einfache Anführungszeichen und liefen so gut. Ihre letzten Beispiele stehen in doppelten Anführungszeichen und wurden daher von Bash nach Expansionssequenzen durchsucht, bevor etwas anderes ausgeführt wurde. Der einzige Grund, warum der erste nicht ausgelöst hat, ist, dass das Leerzeichen ein Unterbrechungszeichen ist, wie oben gezeigt.
quelle
var=word; echo "test '$var'"; echo 'test "$var"'
Wie schon von Caleb gesagt ,
!
wird verwendet, um die Ersetzung der Bash-Historie aufzurufen.Wenn Sie wie ich das Gefühl haben, dass Sie eine solche Funktion nicht benötigen, können Sie sie deaktivieren, indem Sie die folgende Zeile einfügen
~/.bashrc
:Ich brauche es nicht , weil die Geschichte durch den Pfeil nach oben und zurückgewonnen werden Ctrl- rinkrementelle Rückwärtssuche. Eine detaillierte Liste der Verknüpfungen finden Sie in der bash-Handbuchseite im Abschnitt Befehle zum Bearbeiten des Verlaufs.
quelle
!!
?set +H
Ihr erstes Beispiel:
könnte auf reduziert werden
In einfachen Anführungszeichen behalten alle Zeichen ihre Literalwerte bei. Dadurch
!
hat seine besondere Bedeutung verloren und die geschichtliche Erweiterung ist nicht vorgeformt.Ihr zweites und drittes Beispiel:
könnte auf reduziert werden
'! p'
und'!p'
sind im Wesentlichen Teile der doppelt zitierten Zeichenfolgen.In doppelte Anführungszeichen, erhalten alle Charaktere ihre Literalwerte ausnehmen
$
,`
,\
und!
.Dies impliziert, dass die einfachen Anführungszeichen von
'! p'
und'!p'
ihre spezielle Bedeutung verloren haben (dh nicht in der Lage zu fliehen!
), aber!
dennoch ihre spezielle Bedeutung behalten, sodass die Geschichtserweiterung durchgeführt wird.Wenn
!
jedoch ein Leerzeichen folgt, wird keine Verlaufserweiterung durchgeführt.Zitat aus
man bash
:quelle