Wie kann ich in bash einem Ausrufezeichen entkommen?

183

Ich möchte so etwas tun bzr commit -m "It works!". Ich kann dem Ausrufezeichen irgendwie entkommen, indem ich tue bzr commit -m "It works\!". Meine Festschreibungsmeldung enthält dann jedoch den umgekehrten Schrägstrich. Wie kann ich mich dem Ausrufezeichen entziehen, ohne den Backslash zu beachten?

Matthew
quelle
1
Das bzr commit -m "It works"!funktioniert auch.
kba
1
Wie ich bzr commit -m "It works!"
vorhin
Ein noch skurrilerer Fall mit verschachtelten Anführungszeichen: stackoverflow.com/questions/22125658/…
Ciro Santilli
1
Obwohl die akzeptierte Antwort eine gute Lösung für Ihre Commit-Probleme darstellt, ist sie meiner Meinung nach keine Antwort auf das eigentliche Problem: Erweiterung des Bash-Verlaufs . Bitte überlegen Sie, Dennis 'Antwort zu akzeptieren.
Arjan

Antworten:

153

Da Sie nicht auf bash angewiesen sind, um Variablen in Ihrer Festschreibungsmeldung zu erweitern, können Sie stattdessen einfache Anführungszeichen verwenden. Zeichenfolgen in einfachen Anführungszeichen werden nicht durch Bash erweitert.

bzr commit -m 'This does work!' 
Benjamin Bannier
quelle
24
Da war die Frage "Wie entkomme ich einem Ausrufezeichen?" und nicht "Wie erweitere ich ein Ausrufezeichen nicht?" Ich denke nicht, dass dies gültig ist. In manchen Fällen (z. B. beim Übergeben von Apostrophen und Ausrufezeichen in derselben Befehlszeile) funktioniert dies nicht. Die Antwort unten funktioniert viel besser, um das zu tun, was viele Menschen brauchen.
Jann
7
@Jann: Da haben Sie zu 100% Recht, aber ich denke, hier ist das Problem, bei dem es so viele Fragen zum Superuser gibt: Beantworten wir die Frage auf den Punkt oder helfen wir den Leuten, ihr spezifisches Problem zu lösen. Ich denke, dass beide Möglichkeiten nützlich sein können, und dies war auf der Suche nach Hilfe zu einem bestimmten Thema.
Benjamin Bannier
touché! Dies war ein spezifisches Problem. Ich möchte nur eine Antwort auf meine Fragen, um sie in vielen Situationen verwenden zu können. pS: Der Grund, warum ich dies erwähnte, war, dass ich sowohl ein Apostroph als auch ein Ausrufezeichen an ein Perl-Programm übergeben musste, und ich brauchte die folgende Lösung. :)
Jann
Ich stimme sowohl Benjamin als auch Jann zu, habe aber eine Ablehnung gegeben. Der Titel der Frage wird von Suchmaschinen indiziert, und so bin ich hierher gekommen, und wahrscheinlich kommen die meisten Benutzer hierher. Aus diesem Grund halte ich es für wichtig, dass die eigentliche Frage das dahinter stehende Problem widerspiegelt. In anderen Foren wird geraten (fast gezwungen), genau zu fragen, wonach sie suchen. Die Beantwortung schlecht formulierter Fragen unterstützt die Schlamperei und das ist der genaue Grund für meine Ablehnung hier. Als Kompromiss / Lösung schlage ich vor, die Überschrift so anzupassen, dass sie dem tatsächlichen Problem entspricht.
ChristophK
153

Ist hier eine andere Methode, wenn Sie doppelte Anführungszeichen sowie das Ausrufezeichen wünschen:

echo "It's broken"'!'

Dies funktioniert auch, wenn sich das !nicht am Ende der Zeile befindet.

Zum Beispiel:

echo "hello there"'!'" and goodbye"

Bonus: Eine ähnliche Technik verwendet werden kann , zu entkommen beliebigen Text in Sh oder Bash (mit Hilfe von sed): siehe die ersten Option in dieser Antwort . Wenn Sie bash-completioninstalliert haben, ist die quote()Funktion wahrscheinlich bereits verfügbar.

jwd
quelle
4
Netter Tipp, JWD. Ich wusste nicht, dass Bash-Strings einfach durch Weglassen von Leerzeichen verkettet werden können.
Alan H.
Befindet sich das Ausrufezeichen am Ende der Zeichenfolge, echo "Happy birthday!"funktionieren Sie im Klartext wie erwartet. Andernfalls können Sie es mit einem Backslash umgehen, aber der Backslash wird auch gedruckt. XD Bash ist nichts für schwache Nerven :)
h4unt3r
@ h4unt3r: Seltsam, das ist nicht meine Erfahrung. Für mich echo "Happy Birthday!"gibt 2 Zeilen aus. Das erste ist echo "Happy birthday"(kein Ausrufezeichen) und das zweite ist "Alles Gute zum Geburtstag" (wieder kein Ausrufezeichen). Haben Sie die Verlaufserweiterung aktiviert, wenn Sie diesen Test durchführen?
Mittwoch,
@jwd welche Version von Bash laufen Sie? Ich habe immer seine Expansion auf. Hast du versehentlich zwei benutzt !! für deinen Test?
h4unt3r
@ h4unt3r: version 4.1.2(1)-release (x86_64-redhat-linux-gnu)definitiv nur einer !wird verwendet. Ich habe histexpandanwesend in $SHELLOPTS. Ich habe jedoch gerade versucht, 4.3.18 (2) auf einem anderen Computer zu veröffentlichen, und es verhält sich so, wie Sie es beschrieben haben. Ich denke, es war ein Fehler, der behoben wurde.
JWD
66

Schalten Sie Geschichte Expansion :

set +H

oder

set +o histexpand

Sie können einen dieser Befehle zu Ihrem hinzufügen, ~/.bashrcwenn Sie normalerweise keine Verlaufserweiterung verwenden.

Bash 4.3 hat einen Sonderfall hinzugefügt :

Das Verlaufserweiterungszeichen wird auch dann als in Anführungszeichen gesetzt behandelt, wenn es unmittelbar vor dem schließenden doppelten Anführungszeichen in einer Zeichenfolge in Anführungszeichen steht

Dennis Williamson
quelle
Danke - das hat funktioniert, aber ich musste es tun set +o histexpand, nicht set -o histexpand. Könnten Sie Ihre Antwort bearbeiten, um dies zu beheben?
Matthew
Ups, Tippfehler, sorry. Fest.
Dennis Williamson
ausgezeichnet! suchte dies für AGES .... thx vm! als Flucht nicht funktionieren ... Ich möchte nicht auch einfache Anführungszeichen verwenden ... Ich werde dies zu meinem .bashrcDank hinzufügen !!, nie !in Skripten verwendet und für nichts !! Es war immer beunruhigend ...
Aquarius Power
Das ist so toll! echo "@AquariusPower!"
Joehanna
12

Verwenden Sie einfache Anführungszeichen (') anstelle von doppelten Anführungszeichen ("). Einfache Anführungszeichen deaktivieren die gesamte Interpretation der Inhalte in ihnen, während doppelte Anführungszeichen nur einige deaktivieren.

bzr commit -m 'It works!'
KeithB
quelle
4

Ich habe gerade einen anderen Weg gefunden, der zumindest mit echoStrings (Sätzen) funktioniert, die Sie mit einem Ausrufezeichen versehen möchten. Es führt mehr oder weniger einen End-Run um Bash histexpand durch und dauert nur ein bisschen länger, um Code zu erstellen.

Das Hexadezimal für ein Ausrufezeichen (siehe http://www.ascii-code.com/ ) ist 21. Wenn Sie also \x21das Ende Ihrer Zeichenfolge angeben echo -e $foo, geben Sie $fooein eigenes erweitertes Echo foo=$(echo -e "$foo")aus bekomme wenn du echo $foowieder den string mit einem !am ende hast . Und auch keine Schaltverzögerung.

Funktioniert auf jeden Fall in Bash 4+. Frühere Versionen, ymmv.

SilberärmelX
quelle
Hmmm bei mir klappt es nicht.
lzap
Ich verstehe nicht, was Sie über das Echo selbst sagen. 'echo -e' und 'printf' interpretieren geschützte Oktal-, Hex- und Unicode-Codes. In Fällen, in denen Sie eine dieser Optionen verwenden, können Sie "\ 041" (das Oktal für "!") Oder "\ x21" (das Hex) als Ersatz für das Ausrufezeichen verwenden. Zum Beispiel: printf "OMG\041". Wenn Sie eine Zeichenfolge in doppelten Anführungszeichen erstellen, die weder echo noch printf enthält, können Sie sie $(echo -e "\041")an der Stelle, an der sich das Ausrufezeichen befinden soll, in die Zeichenfolge einbetten . Wie folgt aus : bzr commit -m "This is a great commit$(echo -e "\041")".
Todd Walton