Angenommen, Sie haben einen Bash alias
wie:
alias rxvt='urxvt'
das funktioniert gut.
Jedoch:
alias rxvt='urxvt -fg '#111111' -bg '#111111''
wird nicht funktionieren und auch nicht:
alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''
Wie können Sie also das Öffnen und Schließen von Anführungszeichen in einer Zeichenfolge abgleichen, wenn Sie den Anführungszeichen entkommen sind?
alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
scheint unansehnlich, obwohl es die gleiche Zeichenfolge darstellen würde, wenn Sie sie so verketten dürfen.
"\""
sollten diese nach Möglichkeit der Antwort von @ liori vorgezogen werden.Antworten:
Wenn Sie wirklich einfache Anführungszeichen in der äußersten Ebene verwenden möchten, denken Sie daran, dass Sie beide Arten von Anführungszeichen kleben können. Beispiel:
Erklärung, wie dies
'"'"'
als gerecht interpretiert wird'
:'
Beenden Sie das erste Anführungszeichen mit einfachen Anführungszeichen."
Starten Sie das zweite Zitat mit doppelten Anführungszeichen.'
Zitierter Charakter."
Beenden Sie das zweite Anführungszeichen mit doppelten Anführungszeichen.'
Beginnen Sie das dritte Zitat mit einfachen Anführungszeichen.Wenn Sie keine Leerzeichen zwischen (1) und (2) oder zwischen (4) und (5) platzieren, interpretiert die Shell diese Zeichenfolge als ein einziges langes Wort.
quelle
alias splitpath='echo $PATH | awk -F : '"'"'{print "PATH is set to"} {for (i=1;i<=NF;i++) {print "["i"]",$i}}'"'"
Es funktioniert, wenn die Alias-Zeichenfolge sowohl einfache als auch doppelte Anführungszeichen enthält!alias serve_this_dir='ruby -rrack -e "include Rack;Handler::Thin.run Builder.new{run Directory.new'"'"''"'"'}"'
'\''
in den meisten Kontexten weitaus besser lesbar ist als'"'"'
. Tatsächlich unterscheidet sich Ersteres fast immer klar innerhalb einer Zeichenfolge in einfachen Anführungszeichen und ist daher nur eine Frage der semantischen Zuordnung zu der Bedeutung "Es ist ein entkommenes Anführungszeichen", wie dies bei\"
Zeichenfolgen in doppelten Anführungszeichen der Fall ist . Letzteres fügt sich in eine Zeile mit Anführungszeichen ein und muss in vielen Fällen sorgfältig geprüft werden, um eine ordnungsgemäße Unterscheidung zu ermöglichen.Ich ersetze immer nur jedes eingebettete einfache Anführungszeichen durch die folgende Sequenz
'\''
(dh Anführungszeichen-Backslash-Anführungszeichen), die die Zeichenfolge schließt, ein maskiertes einfaches Anführungszeichen anfügt und die Zeichenfolge erneut öffnet.Ich rufe in meinen Perl-Skripten häufig eine "Anführungszeichen" -Funktion auf, um dies für mich zu tun. Die Schritte wären:
Dies kümmert sich so ziemlich um alle Fälle.
Das Leben macht mehr Spaß, wenn Sie es
eval
in Ihre Shell-Skripte einführen . Sie müssen im Wesentlichen alles neu zitieren!Erstellen Sie beispielsweise ein Perl-Skript namens quotify, das die obigen Anweisungen enthält:
Verwenden Sie es dann, um eine korrekt in Anführungszeichen gesetzte Zeichenfolge zu generieren:
Ergebnis:
die dann in den Alias-Befehl kopiert / eingefügt werden kann:
(Wenn Sie den Befehl in eine Auswertung einfügen müssen, führen Sie das Anführungszeichen erneut aus:
Ergebnis:
die kopiert / in eine Bewertung eingefügt werden kann:
quelle
set -x
und ,echo "here's a string"
und Sie werden feststellen , dass bash ausführt sehenecho 'here'\''s a string'
. (set +x
um normales Verhalten zurückzugeben)Da die Bash 2.04- Syntax
$'string'
(statt nur'string'
; Warnung: nicht verwechseln mit$('string')
) ein weiterer Anführungsmechanismus ist, der ANSI C-ähnliche Escape-Sequenzen ermöglicht und eine Erweiterung auf eine einfache Anführungszeichenversion ermöglicht.Einfaches Beispiel:
In Ihrem Fall:
Häufige Escape-Sequenzen funktionieren wie erwartet:
Unten finden Sie eine Kopie + eingefügte Dokumentation aus
man bash
(Version 4.4):Wörter der Form $ 'string' werden speziell behandelt. Das Wort wird zu Zeichenfolge erweitert, wobei Zeichen mit Backslash-Escapezeichen gemäß ANSI C-Standard ersetzt werden. Backslash-Escape-Sequenzen werden, falls vorhanden, wie folgt dekodiert:
Das erweiterte Ergebnis wird in einfachen Anführungszeichen gesetzt, als ob das Dollarzeichen nicht vorhanden gewesen wäre.
Siehe Zitate und Flucht: ANSI C wie Strings auf bash-hackers.org um weitere Informationen zu Wiki. Beachten Sie auch, dass in der Datei "Bash Changes" ( Übersicht hier ) häufig Änderungen und Fehlerbehebungen im Zusammenhang mit dem
$'string'
Angebotsmechanismus erwähnt werden.Laut unix.stackexchange.com Wie verwende ich ein Sonderzeichen als normales? Es sollte (mit einigen Variationen) in Bash, Zsh, Mksh, Ksh93 und FreeBSD und Busybox Sh funktionieren.
quelle
echo $'foo\'b!ar'
=>!ar': event not found
> echo $BASH_VERSION
4.2.47(1)-release
> echo $'foo\'b!ar'
foo'b!ar
$'
wahrscheinlich einfachsten Weg, es selbst auf älteren Systemen zu versuchen.e. Bash no longer inhibits C-style escape processing ($'...') while performing pattern substitution word expansions.
Entnommen aus www.case.edu/php/chet/bash/CHANGES . Funktioniert immer noch in 4.3.42, aber nicht in 4.3.48.Ich sehe den Eintrag nicht in seinem Blog (Link pls?), Aber laut Gnu-Referenzhandbuch :
Bash wird also nicht verstehen:
alias x='y \'z '
Sie können dies jedoch tun, wenn Sie doppelte Anführungszeichen verwenden:
quelle
Ich kann bestätigen, dass die Verwendung
'\''
eines einfachen Anführungszeichens in einer Zeichenfolge in einfachen Anführungszeichen in Bash funktioniert, und dies kann auf die gleiche Weise erklärt werden wie das Argument "Kleben" von früher im Thread. Angenommen, wir haben eine Zeichenfolge in'A '\''B'\'' C'
Anführungszeichen : (Alle Anführungszeichen hier sind einfache Anführungszeichen). Wenn es an echo übergeben wird, wird Folgendes ausgegeben :A 'B' C
. In jedem'\''
der ersten Anführungszeichen wird die aktuelle Zeichenfolge in einfachen Anführungszeichen geschlossen, im Folgenden wird\'
ein einfaches Anführungszeichen an die vorherige Zeichenfolge geklebt (\'
eine Möglichkeit, ein einfaches Anführungszeichen anzugeben, ohne eine Zeichenfolge in Anführungszeichen zu setzen), und im letzten Anführungszeichen wird eine weitere Zeichenfolge in einfachen Anführungszeichen geöffnet.quelle
alias something='A '\''B'\'' C'
führt dazu, dasssomething
es sich um eine einzelne Zeichenfolge handelt. Auch wenn die rechte Seite der Zuweisung technisch gesehen keine einzelne Zeichenfolge ist, halte ich es nicht für wichtig.'A ' + ' + 'B' + ' + ' C'
. Mit anderen Worten, eine Lösung zum Einfügen von einfachen Anführungszeichen in eine Zeichenfolge in einfachen Anführungszeichen sollte es mir ermöglichen, eine solche Zeichenfolge selbst zu erstellen und zu drucken. Diese Lösung funktioniert in diesem Fall jedoch nicht.STR='\''; echo $STR
. Wie geplant, lässt BASH dies nicht wirklich zu.'\''
funktioniert für Bash. Können Sie darauf hinweisen, welche Abschnitte von gnu.org/software/bash/manual/bashref.html ein solches Verhalten angeben?Beide Versionen funktionieren entweder mit Verkettung unter Verwendung des maskierten einfachen Anführungszeichens (\ ') oder mit Verkettung durch Einschließen des einfachen Anführungszeichens in doppelte Anführungszeichen ("'").
Der Autor der Frage bemerkte nicht, dass am Ende seines letzten Fluchtversuchs ein zusätzliches einfaches Anführungszeichen (') stand:
Wie Sie im vorherigen schönen Stück ASCII / Unicode-Grafik sehen können, folgt auf das letzte maskierte einfache Anführungszeichen (\ ') ein unnötiges einfaches Anführungszeichen ('). Die Verwendung eines Syntax-Textmarkers wie dem in Notepad ++ kann sich als sehr hilfreich erweisen.
Gleiches gilt für ein anderes Beispiel wie das folgende:
Diese beiden schönen Beispiele für Aliase zeigen auf sehr komplizierte und verschleierte Weise, wie eine Datei in einer Reihe angeordnet werden kann. Das heißt, aus einer Datei mit vielen Zeilen erhalten Sie nur eine Zeile mit Kommas und Leerzeichen zwischen den Inhalten der vorherigen Zeilen. Um den vorherigen Kommentar zu verstehen, ist das Folgende ein Beispiel:
quelle
Einfaches Beispiel für das Entkommen von Anführungszeichen in der Shell:
Dazu beenden Sie bereits geöffnete (
'
), platzieren Escape (\'
) und öffnen dann eine weitere ('
). Diese Syntax funktioniert für alle Befehle. Es ist sehr ähnlich wie bei der ersten Antwort.quelle
Ich gehe nicht speziell auf das Problem des Zitierens ein, da es manchmal nur sinnvoll ist, einen alternativen Ansatz in Betracht zu ziehen.
die Sie dann anrufen können als:
Die Idee ist, dass Sie dies jetzt ohne Rücksicht auf Anführungszeichen aliasisieren können:
oder, wenn Sie das
#
aus irgendeinem Grund in alle Anrufe einbeziehen müssen:die Sie dann anrufen können als:
dann lautet ein Alias natürlich:
(Ups, ich denke, ich habe das Zitat irgendwie angesprochen :)
quelle
Da man keine einfachen Anführungszeichen in einfache Anführungszeichen setzen kann, ist die einfachste und am besten lesbare Option die Verwendung einer HEREDOC-Zeichenfolge
Im obigen Code wird das HEREDOC an den
cat
Befehl gesendet und die Ausgabe davon wird einer Variablen über die Befehlsersetzungsnotation zugewiesen$(..)
Es ist erforderlich, ein einfaches Anführungszeichen um das HEREDOC zu setzen, da es sich innerhalb von a befindet
$()
quelle
dash
bei der Standard-Shell in Ubuntu-Upstart-Skripten und anderswo.Ich benutze nur Shell-Codes .. zB
\x27
oder\\x22
wie zutreffend. Kein Ärger, nie wirklich.quelle
x27
(auf Centos 6.6)Die meisten dieser Antworten treffen auf den speziellen Fall, nach dem Sie fragen. Es gibt einen allgemeinen Ansatz , dass ein Freund und ich habe entwickelt, das für beliebige zitieren , falls erlaubt müssen Sie zitieren bash Befehle durch mehrere Schichten von Shell - Erweiterung, zum Beispiel durch ssh,
su -c
,bash -c
etc. Es gibt einen Kern primitiv ist , dass Sie benötigen, hier in native bash:Dies macht genau das, was es sagt: Es zitiert jedes Argument einzeln (natürlich nach der Bash-Erweiterung):
Es ist das Offensichtliche für eine Expansionsschicht:
(Beachten Sie, dass die doppelten Anführungszeichen
$(quote_args ...)
erforderlich sind, um das Ergebnis in ein einziges Argument umzuwandelnbash -c
.) Und es kann allgemeiner verwendet werden, um durch mehrere Erweiterungsebenen richtig zu zitieren:Das obige Beispiel:
quote_args
einzeln in das Innere und kombiniert dann die resultierende Ausgabe zu einem einzigen Argument mit den inneren doppelten Anführungszeichen.bash
,-c
und das schon einmal zitierte Ergebnis aus Schritt 1, und kombinieren dann das Ergebnis in ein einziges Argument mit den äußeren Anführungszeichen.bash -c
.Das ist die Idee auf den Punkt gebracht. Sie können einige ziemlich komplizierte Dinge damit machen, aber Sie müssen vorsichtig sein, in welcher Reihenfolge die Bewertung erfolgt und welche Teilzeichenfolgen zitiert werden. Zum Beispiel machen die folgenden Dinge die falschen Dinge (für eine Definition von "falsch"):
Im ersten Beispiel, dehnt bash sofort
quote_args cd /; pwd 1>&2
in zwei getrennte Befehle,quote_args cd /
undpwd 1>&2
, so wie vor der CWD ist ,/tmp
wenn derpwd
Befehl ausgeführt wird. Das zweite Beispiel zeigt ein ähnliches Problem beim Globbing. In der Tat tritt das gleiche Grundproblem bei allen Bash-Erweiterungen auf. Das Problem hierbei ist, dass eine Befehlssubstitution kein Funktionsaufruf ist: Sie wertet buchstäblich ein Bash-Skript aus und verwendet seine Ausgabe als Teil eines anderen Bash-Skripts.Wenn Sie versuchen, den Shell-Operatoren einfach zu entkommen, schlagen Sie fehl, da die resultierende Zeichenfolge, an die übergeben
bash -c
wird, nur eine Folge von Zeichenfolgen in Anführungszeichen ist, die dann nicht als Operatoren interpretiert werden. Dies ist leicht zu erkennen, wenn Sie die Zeichenfolge wiedergeben, die dies tun würde wurden an bash übergeben:Das Problem hier ist, dass Sie zu viel zitieren. Was Sie brauchen, ist, dass die Operatoren nicht als Eingabe für das Gehäuse in Anführungszeichen gesetzt werden
bash -c
, was bedeutet, dass sie sich außerhalb der$(quote_args ...)
Befehlsersetzung befinden müssen.Folglich müssen Sie im allgemeinsten Sinne jedes Wort des Befehls in Shell zitieren, das zum Zeitpunkt der Befehlssubstitution nicht erweitert werden soll, und keine zusätzlichen Anführungszeichen auf die Shell-Operatoren anwenden:
Sobald Sie dies getan haben, ist die gesamte Zeichenfolge ein faires Spiel, um weitere Bewertungsstufen zu zitieren:
usw.
Diese Beispiele können overwrought scheinen gegeben , dass Worte wie
success
,sbin
undpwd
nicht seine muschel zitiert müssen, aber der entscheidende Punkt zu erinnern , wenn ein Skript unter beliebiger Eingabe zu schreiben ist , dass man alles zitieren wollen Sie nicht absolut sicher doesn‘ Ich brauche kein Zitat, weil Sie nie wissen, wann ein Benutzer eine einwirftRobert'; rm -rf /
.Um besser zu verstehen, was unter der Decke vor sich geht, können Sie mit zwei kleinen Hilfsfunktionen herumspielen:
Dadurch werden alle Argumente zu einem Befehl aufgelistet, bevor sie ausgeführt werden:
quelle
vagrant ssh -c {single-arg} guest
. Das{single-arg}
muss als ein einzelnes Argument behandelt werden, da Vagrant das nächste Argument danach als Gastnamen verwendet. Die Reihenfolge kann nicht geändert werden. Aber ich musste einen Befehl und seine Argumente übergeben{single-arg}
. Also habe ich Ihren verwendetquote_args()
, um den Befehl und seine Argumente zu zitieren und das Ergebnis in doppelte Anführungszeichen zu setzen, und es hat wie ein Zauber funktioniert :vagrant ssh -c "'command' 'arg 1 with blanks' 'arg 2'" guest
. Vielen Dank!!!IMHO ist die wirkliche Antwort, dass Sie einfache Anführungszeichen in einfachen Anführungszeichen nicht entkommen können.
Es ist unmöglich.
Wenn wir davon ausgehen, dass wir Bash verwenden.
Aus dem Bash-Handbuch ...
Sie müssen einen der anderen String-Escape-Mechanismen verwenden "oder \
Es ist nichts Magisches daran,
alias
dass es einfache Anführungszeichen erfordert.Beide folgenden Arbeiten in Bash.
Letzterer verwendet \, um dem Leerzeichen zu entkommen.
Es gibt auch nichts Magisches an # 111111, das einfache Anführungszeichen erfordert.
Die folgenden Optionen erzielen das gleiche Ergebnis wie die beiden anderen Optionen, da der rxvt-Alias wie erwartet funktioniert.
Sie können dem lästigen # auch direkt entkommen
quelle
Verwenden Sie im angegebenen Beispiel einfach doppelte Anführungszeichen anstelle von einfachen Anführungszeichen als äußeren Escape-Mechanismus:
Dieser Ansatz eignet sich für viele Fälle, in denen Sie nur eine feste Zeichenfolge an einen Befehl übergeben möchten: Überprüfen Sie einfach, wie die Shell die Zeichenfolge in doppelten Anführungszeichen durch a interpretiert
echo
, und maskieren Sie Zeichen bei Bedarf mit Backslash.Im Beispiel sehen Sie, dass doppelte Anführungszeichen ausreichen, um die Zeichenfolge zu schützen:
quelle
Natürlich wäre es einfacher, einfach mit doppelten Anführungszeichen zu umgeben, aber wo liegt die Herausforderung dabei? Hier ist die Antwort nur in einfachen Anführungszeichen. Ich verwende stattdessen eine Variable,
alias
damit es einfacher ist, sie als Proof zu drucken, aber es ist dasselbe wie bei der Verwendungalias
.Erläuterung
Der Schlüssel ist, dass Sie das einfache Anführungszeichen schließen und es so oft öffnen können, wie Sie möchten. Zum Beispiel
foo='a''b'
ist das gleiche wiefoo='ab'
. Sie können also das einfache Anführungszeichen schließen, ein wörtliches einfaches Anführungszeichen\'
eingeben und das nächste einfache Anführungszeichen erneut öffnen.Aufschlüsselungsdiagramm
Dieses Diagramm verdeutlicht anhand von Klammern, wo die einfachen Anführungszeichen geöffnet und geschlossen werden. Anführungszeichen sind nicht wie in Klammern "verschachtelt". Sie können auch auf die korrekte Farbhervorhebung achten. Die zitierten Saiten sind kastanienbraun, während die
\'
schwarz sind.(Dies ist im Wesentlichen die gleiche Antwort wie die von Adrian, aber ich denke, das erklärt es besser. Auch seine Antwort enthält am Ende zwei überflüssige einfache Anführungszeichen.)
quelle
'\''
Methode Ich empfehle gegenüber der'"'"'
Methode, die für Menschen oft schwerer zu lesen ist.Hier ist eine Ausarbeitung zu The One True Answer, auf die oben Bezug genommen wurde:
Manchmal lade ich mit rsync über ssh herunter und muss einem Dateinamen mit einem 'darin ZWEIMAL entkommen! (OMG!) Einmal für Bash und einmal für SSH. Hier gilt das gleiche Prinzip alternierender Anführungszeichen.
Nehmen wir zum Beispiel an, wir wollen: Louis Therouxs LA Stories ...
Und siehe da! Sie landen damit:
Das ist eine Menge Arbeit für ein kleines Kind - aber los geht's
quelle
Erklärung zur Implementierung:
doppelte Anführungszeichen, damit wir einfache einfache Anführungszeichen ausgeben und die
${...}
Syntax verwenden könnenDas Suchen und Ersetzen von bash sieht folgendermaßen aus:
${varname//search/replacement}
wir ersetzen
'
durch'\''
'\''
codiert eine Single'
wie folgt:'
beendet das einfache Anführungszeichen\'
codiert a'
(der Backslash wird benötigt, da wir uns nicht in Anführungszeichen befinden)'
Startet das einfache Anführungszeichen erneutbash verkettet automatisch Zeichenfolgen ohne Leerzeichen dazwischen
Es gibt ein
\
vor jedem\
und'
weil das die Fluchtregeln für sind${...//.../...}
.PS Codieren Sie immer in Zeichenfolgen in einfachen Anführungszeichen, da diese viel einfacher sind als Zeichenfolgen in doppelten Anführungszeichen.
quelle
Eine andere Möglichkeit, das Problem zu vieler Ebenen verschachtelter Anführungszeichen zu beheben:
Sie versuchen, zu viel in einen zu kleinen Raum zu stopfen, verwenden Sie also eine Bash-Funktion.
Das Problem ist, dass Sie versuchen, zu viele Verschachtelungsebenen zu haben, und die grundlegende Alias-Technologie nicht leistungsfähig genug ist, um sie zu berücksichtigen. Verwenden Sie eine Bash-Funktion wie diese, damit die Ticks mit einfachen, doppelten Anführungszeichen und übergebenen Parametern wie erwartet normal behandelt werden:
Dann können Sie Ihre $ 1- und $ 2-Variablen sowie einfache, doppelte Anführungszeichen und Back-Ticks verwenden, ohne sich Gedanken über die Alias-Funktion machen zu müssen, die deren Integrität beeinträchtigt.
Dieses Programm druckt:
quelle
Wenn Sie GNU Parallel installiert haben, können Sie das interne Angebot verwenden:
Ab Version 20190222 können Sie sogar
--shellquote
mehrmals:Die Zeichenfolge wird in allen unterstützten Shells (nicht nur
bash
) zitiert .quelle
Diese Funktion:
ermöglicht das Zitieren von
'
innen'
. Verwenden Sie wie folgt:Wenn die zu zitierende Zeile komplexer wird, z. B. doppelte Anführungszeichen gemischt mit einfachen Anführungszeichen, kann es ziemlich schwierig werden, die Zeichenfolge innerhalb einer Variablen in Anführungszeichen zu setzen. Wenn solche Fälle auftreten, schreiben Sie die genaue Zeile, die Sie zitieren müssen, in ein Skript (ähnlich wie dieses).
Wird ausgegeben:
Alle korrekt in Anführungszeichen gesetzten Zeichenfolgen in einfachen Anführungszeichen.
quelle
Wenn Sie die Shell-Zeichenfolge in Python 2 oder Python 3 generieren, können die folgenden Argumente hilfreich sein:
Dies wird Folgendes ausgeben:
quelle
Hier sind meine zwei Cent - für den Fall, dass man
sh
portabel und nicht nur spezifisch sein möchtebash
(die Lösung ist jedoch nicht zu effizient, da sie ein externes Programm startet -sed
):quote.sh
(oder nurquote
) irgendwo auf IhrePATH
:Ein Beispiel:
Und das konvertiert natürlich zurück:
Erläuterung: Grundsätzlich müssen wir die Eingabe in Anführungszeichen setzen
'
und dann auch jedes einzelne Anführungszeichen durch dieses Mikromonster ersetzen:'"'"'
(Beenden Sie das erste Anführungszeichen mit einer Paarung'
, umgehen Sie das gefundene einfache Anführungszeichen, indem Sie es mit doppelten Anführungszeichen umschließen -"'"
und dann endlich eine neue Öffnung Apostroph ausgeben'
, oder in pseudo-Notation:' + "'" + ' == '"'"'
)Eine Standardmethode hierfür ist die Verwendung
sed
des folgenden Substitutionsbefehls:Ein kleines Problem ist jedoch, dass man, um das in der Shell zu verwenden, all diesen einfachen Anführungszeichen im sed-Ausdruck selbst entkommen muss - was zu so etwas führt
(und eine gute Möglichkeit, dieses Ergebnis zu erzielen, besteht darin, den ursprünglichen Ausdruck
s/\(['][']*\)/'"\1"'/g
den Skripten von Kyle Rose oder George V. Reilly zuzuführen).Schließlich ist es irgendwie sinnvoll zu erwarten, dass die Eingabe von kommt
stdin
- da das Weiterleiten über Befehlszeilenargumente bereits zu viel Mühe bereiten kann.(Oh, und vielleicht möchten wir eine kleine Hilfemeldung hinzufügen, damit das Skript nicht hängen bleibt, wenn jemand es nur ausführt und sich
./quote.sh --help
fragt, was es tut.)quelle
Hier ist eine andere Lösung. Diese Funktion nimmt ein einzelnes Argument und zitiert es angemessen mit dem einfachen Anführungszeichen, genau wie in der obigen Antwort erklärt:
Sie können es also folgendermaßen verwenden:
quelle