it-swarm.com.de

Warum funktioniert alias foo = 'echo "Dies ist ein Zitat: \'" 'nicht?

Um mich daran zu erinnern, wenn ich versuche, shopt in Zsh anstelle von setopt zu verwenden, habe ich den folgenden Alias ​​erstellt und ihn zuerst an einer Shell-Eingabeaufforderung getestet:

$ alias shopt='echo "You\'re looking for setopt. This is Z Shell, man, not Bash."'

Obwohl die äußeren einfachen Anführungszeichen und die inneren doppelten Anführungszeichen übereinstimmten und der Apostroph entkommen war, wurde ich aufgefordert, das Schließen der Anführungszeichen zu beenden mit:

dquote > _

Was ist los?

Es stellte sich heraus, dass die Flucht ignoriert wurde oder dass sie aufgrund mehrerer Interpretationsebenen doppelt entkommen musste ... Um diese Theorie zu testen, habe ich versucht, sie doppelt zu entkommen (und sie dreimal zu entkommen und so weiter) on) bis:

alias shopt='echo "You\\\\\\\\\\\\\\\\\\\\\\'re looking for setopt. This is Z Shell, man, not Bash." '

und hat nie ein anderes Verhalten gesehen. Das macht für mich keinen Sinn. Was für ein seltsamer Voodoo verhindert, dass sich die Shell so verhält, wie ich es erwartet habe?

Die praktische Lösung besteht darin, keine Anführungszeichen für echo zu verwenden, da keine wirklich benötigt werden, und doppelte Anführungszeichen für alias zu verwenden und dem Apostroph zu entkommen, damit er beim Text ignoriert wird ist echoed. Dann verschwinden alle praktischen Probleme.

Können Sie mir helfen? Ich brauche eine Lösung für dieses verwirrende Problem.

23
iconoclast

Dies ist zsh, Mann, nicht fish.

In zsh, wie in jeder Bourne-ähnlichen Shell (und auch csh), einfache Anführungszeichen sind starke Anführungszeichen, es gibt kein Entkommen in ihnen (außer durch Verwendung von rcquotes Optionen als angedeutet von @JdeBP wobei zshrc Anführungszeichen emuliert¹). Sie können kein einfaches Anführungszeichen in einer Zeichenfolge in einfachen Anführungszeichen haben. Sie müssen zuerst die Zeichenfolge in einfachen Anführungszeichen schließen und das wörtliche einfache Anführungszeichen mithilfe eines anderen Anführungszeichenmechanismus eingeben (z. B. \ Oder "):

alias shopt='echo "You'\''re looking for setopt. This is Z Shell, man, not Bash."'

Oder:

alias shopt='echo "You'"'"'re looking for setopt. This is Z Shell, man, not Bash."'

Sie können aber auch Folgendes tun:

alias shopt="echo \"You're looking for setopt. This is Z Shell, man, not Bash.\""

("..." Sind schwächere Anführungszeichen, in denen mehrere Zeichen enthalten sind, einschließlich \ (Hier wird das eingebettete ") Sind noch etwas Besonderes).

Oder:

alias shopt=$'echo "You\'re looking for setopt. This is Z Shell, man, not Bash."'

($'...' Ist eine weitere Art von Zitaten aus ksh93, bei der ' Mit \' Maskiert werden kann.).


¹ In rc ist die Shell von Plan9 mit einer Version für Unix-Likes ebenfalls verfügbar, einfache Anführungszeichen sind der einzige Anführungszeichenmechanismus (Backslash und doppelte Anführungszeichen sind dort gewöhnliche Zeichen) Die einzige Möglichkeit, ein wörtliches einfaches Anführungszeichen einzugeben, besteht darin, '' in einfache Anführungszeichen zu setzen. Mit zsh -o rcquotes können Sie also Folgendes tun:

alias shopt = 'echo "Sie suchen nach setopt. Dies ist Z Shell, Mann, nicht Bash."'
43

Die anderen Antworten erklären gut, warum Sie dieses Verhalten sehen. Aber wenn ich einen Vorschlag machen darf, wie dieses Problem tatsächlich gelöst werden kann:

Verwenden Sie keine Aliase für etwas, das auch nur annähernd kompliziert ist.

Sicher, Sie können Ihr Gehirn in Knoten binden, um herauszufinden, wie man N Schichten von Anführungszeichen verschachtelt, aber es lohnt sich selten für einen Alias. Wenn ein Alias ​​so kompliziert ist, dass sein Zitat nicht mehr trivial ist, wechseln Sie einfach zu einer Shell-Funktion:

shopt(){
    echo "You're looking for setopt. This is Z Shell, man, not Bash."
}

Dadurch wird eine ganze Ebene von Anführungszeichen entfernt, Sie können später mehr Code zur Shell-Funktion hinzufügen und es ist im Allgemeinen viel einfacher zu lesen. Es ermöglicht auch eine viel feinere Kontrolle darüber, wie und wo Argumente eingefügt werden, anstelle des Alias-Ansatzes "Ersetzen Sie einfach den Zeilenanfang und lassen Sie die verbleibenden Wörter fallen, wo sie mögen". Beispiel: Geben Sie mit Ihrem (korrigierten) Alias ​​Folgendes ein:

shopt -s some_opt

... dann erhalten Sie diese Ausgabe:

You're looking for setopt. This is Z Shell, man, not Bash. -s some_opt

Das wollten Sie wahrscheinlich nicht. Die Shell-Funktion verwendet alle Argumente, die Sie an sie übergeben, und verwirft sie stillschweigend.

13
Kevin
shopt = 'echo "Du \'

Das ist kein Voodoo. Dies ist ein normales POSIX-Shell-Zitat in Aktion. Es gibt keinen Escape-Mechanismus in Zeichenfolgen in einfachen Anführungszeichen . Sie enden immer beim nächsten einfachen Anführungszeichen. Es gibt eine Z-Shell-Erweiterung, mit der zwei aufeinanderfolgende Zeichenfolgen in einfachen Anführungszeichen ein einfaches Anführungszeichen zwischen sich setzen, das Sie verwenden können. Oder Sie beenden einfach die Zeichenfolge in einfachen Anführungszeichen, verwenden ein maskiertes (oder nicht in einfache Anführungszeichen gesetztes) einfaches Anführungszeichen und beginnen dann eine zweite Zeichenfolge in einfachen Anführungszeichen.

Oder Sie konnten keine Kontraktionen in Ihren Nachrichten verwenden. ☺

Weiterführende Literatur

13
JdeBP

Verwenden Sie für Tage, an denen Sie keine Lust haben, gegen die Anführungszeichen zu kämpfen, ein anderes Zeichen wie Unicode U + 2019 anstelle von ' für Apostrophe.

Drücken und halten Ctrl+Shift und geben Sie u2019 und dieses Zeichen erscheint (ähm ... abhängig von Ihrem Gebietsschema?).

% alias shopt='echo You’re looking for setopt. This is a Z Shell, woman, not Bash.'
% shopt -s dotglob
You’re looking for setopt. This is a Z Shell, woman, not Bash. -s dotglob

Eine solche Verwendung von (U + 2019) ist korrekt, da dieses Zeichen offiziell als Apostroph verwendet werden soll. Der Unicode-Standard, Version 10.0 empfiehlt eine solche Verwendung ausdrücklich. Der Standard erkennt an, dass ' (U + 0027) wird aufgrund seiner Anwesenheit in ASCII und auf Tastaturen) häufig als Apostroph verwendet und scheint dies zuzulassen. Dann heißt es jedoch, dass (U + 2019) ist bevorzugt für Apostrophe, die als Interpunktion verwendet werden (und gibt als Beispiel eine Kontraktion an). Die einzigen Apostrophe, für die (U + 2019) wird nicht bevorzugt, wenn solche als diakritische Zeichen anstelle von Satzzeichen verwendet werden; diese sind am besten geschrieben ʼ (U + 02BC). Aus Apostrophe (S. 276) in Abschnitt 6.2 von der Standard ::

Apostrophe

U + 0027  [~ # ~] Apostroph [~ # ~]  ist das am häufigsten verwendete Zeichen für Apostroph. Aus historischen Gründen ist U + 0027 ein besonders überladener Charakter. In ASCII wird es verwendet, um ein Interpunktionszeichen (z. B. rechtes einfaches Anführungszeichen, linkes einfaches Anführungszeichen, Apostroph-Interpunktion, vertikale Linie oder Primzahl) oder einen Modifikatorbuchstaben (z. B. Apostroph-Modifikator oder akuter Akzent) darzustellen. Satzzeichen brechen im Allgemeinen Wörter; Modifikatorbuchstaben werden im Allgemeinen als Teil eines Wortes betrachtet.

Wenn Text eingestellt ist, U + 2019  RIGHT SINGLE QUOTATION MARK  wird als Apostroph bevorzugt, aber auf den meisten Tastaturen ist nur U + 0027 vorhanden. Software bietet üblicherweise eine Möglichkeit zum automatischen Konvertieren des U + 0027  [~ # ~] Apostroph [~ # ~]  zu einem kontextuell ausgewählten geschweiften Anführungszeichen. In diesen Systemen wird ein U + 0027 im Datenstrom immer als gerade vertikale Linie dargestellt und kann niemals einen geschweiften Apostroph oder ein rechtes Anführungszeichen darstellen.

Buchstabe Apostroph. U + 02BC  MODIFIER LETTER APOSTROPHE  wird bevorzugt, wenn der Apostroph einen Modifikatorbuchstaben darstellen soll (z. B. in Transliterationen, um einen Stimmritzenstopp anzuzeigen). Im letzteren Fall wird es auch als Buchstabenapostroph bezeichnet.

Interpunktionsapostroph. U + 2019  RIGHT SINGLE QUOTATION MARK  wird bevorzugt, wenn das Zeichen ein Interpunktionszeichen darstellen soll, wie bei Kontraktionen: „ Wir waren schon einmal hier. “ In diesem letzteren Fall wird U + 2019 auch als bezeichnet ein Interpunktionsapostroph .

Eine Implementierung kann nicht davon ausgehen, dass der Text des Benutzers immer der Unterscheidung zwischen diesen Zeichen entspricht. Der Text kann aus verschiedenen Quellen stammen, einschließlich der Zuordnung aus anderen Zeichensätzen, die diese Unterscheidung zwischen dem Buchstaben Apostroph und dem Satzzeichen Apostroph/rechtem einfachen Anführungszeichen nicht treffen. In diesem Fall werden alle von ihnen im Allgemeinen durch U + 2019 dargestellt.

Die Semantik von U + 2019 ist daher kontextabhängig. Wenn es beispielsweise auf beiden Seiten von Buchstaben oder Ziffern umgeben ist, verhält es sich wie ein Interpunktionszeichen im Text und trennt keine Wörter oder Zeilen.

5
Zanna

Ein jetzt gelöschter Kommentar gab mir einen Hinweis und brachte mich auf halbem Weg zur Antwort.

Es ist unmöglich, einem einfachen Anführungszeichen in einem einfachen Anführungszeichen zu entkommen.

Diese Einschränkung ist in Zeichenfolgen in doppelten Anführungszeichen nicht vorhanden, da ich in meiner endgültigen Lösung mit Sicherheit einem einfachen Anführungszeichen in einer Zeichenfolge in doppelten Anführungszeichen entkomme:

alias shopt="echo You\'re looking for setopt. This is Z Shell, man, not Bash."
4
iconoclast