1433 Stimmen

Wie werden einfache Anführungszeichen innerhalb von Zeichenketten mit einfachen Anführungszeichen aufgehoben?

Nehmen wir an, Sie haben einen Bash alias mögen:

alias rxvt='urxvt'

was gut funktioniert.

Allerdings:

alias rxvt='urxvt -fg '#111111' -bg '#111111''

wird nicht funktionieren, und das wird es auch nicht:

alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''

Wie lassen sich also öffnende und schließende Anführungszeichen innerhalb einer Zeichenkette zuordnen, wenn Sie Anführungszeichen escaped haben?

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''

scheint unhandlich, obwohl es dieselbe Zeichenkette darstellen würde, wenn man sie auf diese Weise verketten darf.

33 Stimmen

Ist Ihnen klar, dass Sie für Alias keine einfachen Anführungszeichen verwenden müssen? Doppelte Anführungszeichen sind viel einfacher.

8 Stimmen

6 Stimmen

Verschachtelte doppelte Anführungszeichen sind ausweichbar, "\"" daher sollten diese, wann immer möglich, der Antwort von @liori vorgezogen werden.

1927voto

liori Punkte 38648

Wenn Sie wirklich einfache Anführungszeichen in der äußersten Ebene verwenden wollen, denken Sie daran, dass Sie beide Arten von Anführungszeichen kleben können. Beispiel:

 alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
 #                     ^^^^^       ^^^^^     ^^^^^       ^^^^
 #                     12345       12345     12345       1234

Erläuterung, wie '"'"' wird als einfach interpretiert ' :

  1. ' Ende des ersten Zitats, das einfache Anführungszeichen verwendet.
  2. " Beginnen Sie das zweite Zitat in doppelten Anführungszeichen.
  3. ' Zitiertes Zeichen.
  4. " Zweites Zitat in doppelten Anführungszeichen beenden.
  5. ' Beginnen Sie das dritte Zitat mit einfachen Anführungszeichen.

Wenn Sie keine Leerzeichen zwischen (1) und (2) oder zwischen (4) und (5) setzen, interpretiert die Shell diese Zeichenfolge als ein einziges langes Wort.

6 Stimmen

alias splitpath='echo $PATH | awk -F : '"'"'{print "PATH is set to"} {for (i=1;i<=NF;i++) {print "["i"]",$i}}'"'" Es funktioniert, wenn sowohl einfache als auch doppelte Anführungszeichen in der Alias-Zeichenfolge vorhanden sind!

41 Stimmen

Meine Interpretation: Die Bash verkettet implizit unterschiedlich quotierte String-Ausdrücke.

3 Stimmen

Hat bei mir funktioniert, Beispiel für doppelte Anführungszeichen: alias serve_this_dir='ruby -rrack -e "include Rack;Handler::Thin.run Builder.new{run Directory.new'"'"''"'"'}"'

381voto

Adrian Pronk Punkte 12786

Ich ersetze immer nur jedes eingebettete einfache Anführungszeichen durch die Sequenz: '\'' (d.h.: quote backslash quote quote), der die Zeichenkette schließt, ein maskiertes einfaches Anführungszeichen anhängt und die Zeichenkette wieder öffnet.


Ich habe oft eine "quotify"-Funktion in meine Perl-Skripte eingebaut, die dies für mich erledigt. Die Schritte wären:

s/'/'\\''/g    # Handle each embedded quote
$_ = qq['$_']; # Surround result with single quotes.

Damit sind so gut wie alle Fälle abgedeckt.

Das Leben macht mehr Spaß, wenn man die eval in Ihre Shell-Skripte einfügen. Sie müssen im Grunde alles noch einmal zitieren!

Erstellen Sie zum Beispiel ein Perl-Skript mit dem Namen quotify, das die oben genannten Anweisungen enthält:

#!/usr/bin/perl -pl
s/'/'\\''/g;
$_ = qq['$_'];

und verwenden Sie es dann, um eine Zeichenkette mit korrekten Anführungszeichen zu erzeugen:

$ quotify
urxvt -fg '#111111' -bg '#111111'

Ergebnis:

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

die dann in den Alias-Befehl kopiert/eingefügt werden kann:

alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

(Wenn Sie den Befehl in ein eval einfügen müssen, führen Sie das quotify erneut aus:

 $ quotify
 alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

Ergebnis:

'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''

die in ein eval kopiert/eingefügt werden kann:

eval 'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''

4 Stimmen

Aber das ist nicht Perl. Und wie Steve B. oben mit seinem Verweis auf das "gnu reference manual" dargelegt hat, kann man in der Bash keine Anführungszeichen innerhalb des gleichen Typs von Anführungszeichen entkommen. Und in der Tat müssen sie nicht innerhalb von alternativen Anführungszeichen entkommen, z.B. ist "'" eine gültige einfache Anführungszeichenfolge und '"' ist eine gültige doppelte Anführungszeichenfolge, ohne dass ein Escaping erforderlich ist.

12 Stimmen

@nicerobot: Ich habe ein Beispiel hinzugefügt, das das zeigt: 1) ich nicht versuche, Anführungszeichen innerhalb des gleichen Typs von Anführungszeichen zu vermeiden, 2) auch nicht in alternativen Anführungszeichen, und 3) Perl verwendet wird, um den Prozess der Erzeugung eines gültigen Bash-Strings mit eingebetteten Anführungszeichen zu automatisieren

31 Stimmen

Der erste Absatz allein ist schon die Antwort, die ich gesucht habe.

331voto

mj41 Punkte 2460

Seit Bash 2.04 Syntax $'string' erlaubt eine begrenzte Anzahl von Escapes.

Seit Bash 4.4, $'string' ermöglicht auch den vollständigen Satz von C-Stil-Escapes und das Verhalten in den folgenden Fällen leicht abweicht $'string' in früheren Versionen. (Zuvor war die $('string') Form verwendet werden kann).

Einfaches Beispiel in Bash 2.04 und neuer:

  $> echo $'aa\'bb'
  aa'bb

  $> alias myvar=$'aa\'bb'
  $> alias myvar
  alias myvar='aa'\''bb'

In Ihrem Fall:

$> alias rxvt=$'urxvt -fg \'#111111\' -bg \'#111111\''
$> alias rxvt
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

Übliche Escaping-Sequenzen funktionieren wie erwartet:

\'     single quote
\"     double quote
\\     backslash
\n     new line
\t     horizontal tab
\r     carriage return

Nachfolgend finden Sie eine kopierte und eingefügte Dokumentation aus man bash (Version 4.4):

Wörter der Form $'string' werden besonders behandelt. Das Wort wird zu string expandiert, wobei Backslash-escapte Zeichen gemäß dem ANSI C Standard ersetzt werden. Backslash-Escape-Sequenzen, falls vorhanden, werden wie folgt dekodiert:

    \a     alert (bell)
    \b     backspace
    \e
    \E     an escape character
    \f     form feed
    \n     new line
    \r     carriage return
    \t     horizontal tab
    \v     vertical tab
    \\     backslash
    \'     single quote
    \"     double quote
    \?     question mark
    \nnn   the eight-bit character whose value is the octal 
           value nnn (one to three digits)
    \xHH   the eight-bit character whose value is the hexadecimal
           value HH (one or two hex digits)
    \uHHHH the Unicode (ISO/IEC 10646) character whose value is 
           the hexadecimal value HHHH (one to four hex digits)
    \UHHHHHHHH the Unicode (ISO/IEC 10646) character whose value 
               is the hexadecimal value HHHHHHHH (one to eight 
               hex digits)
    \cx    a control-x character

Das erweiterte Ergebnis wird in einfache Anführungszeichen gesetzt, als ob das Dollarzeichen nicht vorhanden gewesen wäre.


Ver Zitate und Fluchten: ANSI C wie Zeichenketten auf bash-hackers.org wiki für weitere Details. Beachten Sie auch, dass "Bash-Änderungen" Datei ( Übersicht hier ) enthält viele Hinweise auf Änderungen und Fehlerbehebungen im Zusammenhang mit der $'string' Zitiermechanismus.

Laut unix.stackexchange.com Wie kann man ein Sonderzeichen als normales Zeichen verwenden? es sollte (mit einigen Variationen) in bash, zsh, mksh, ksh93 und FreeBSD und busybox sh funktionieren.

0 Stimmen

Verwendet werden, aber die Zeichenkette in Anführungszeichen ist keine echte Zeichenkette in Anführungszeichen, der Inhalt dieser Zeichenkette kann von der Shell interpretiert werden: echo $'foo\'b!ar' => !ar': event not found

3 Stimmen

Auf meinem Rechner > echo $BASH_VERSION 4.2.47(1)-release > echo $'foo\'b!ar' foo'b!ar

1 Stimmen

Ja, das ist der Grund für "may", ich hatte es auf einem Red hat 6.4, sicherlich eine ältere Bash-Version.

61voto

Steve B. Punkte 52372

Ich sehe den Eintrag in seinem Blog nicht (Link bitte?), aber laut der Gnu-Referenzhandbuch :

Einschließen von Zeichen in einfache Anführungszeichen (''') bleibt der wörtliche Wert von jedes Zeichens innerhalb der Anführungszeichen. A einfaches Anführungszeichen darf nicht zwischen einfachen Anführungszeichen stehen, auch wenn ihnen ein Backslash vorausgeht.

so dass Bash es nicht verstehen wird:

alias x='y \'z '

Sie können dies jedoch tun, wenn Sie den Text in doppelte Anführungszeichen setzen:

alias x="echo \'y "
> x
> 'y

1 Stimmen

0 Stimmen

Inhalte, die in doppelten Anführungszeichen eingeschlossen sind, werden ausgewertet, so dass das Einschließen von einfachen Anführungszeichen in doppelte Anführungszeichen, wie von liori vorgeschlagen, die richtige Lösung zu sein scheint.

3 Stimmen

Dies ist die eigentliche Antwort auf die Frage. Auch wenn die akzeptierte Antwort eine Lösung bietet, beantwortet sie technisch gesehen eine Frage, die nicht gestellt wurde.

52voto

mikhail_b Punkte 840

Ich kann bestätigen, dass die Verwendung von '\'' für ein einzelnes Anführungszeichen innerhalb einer Zeichenkette in einfachen Anführungszeichen funktioniert in der Bash, und es kann auf dieselbe Weise erklärt werden wie das "Kleben"-Argument von weiter oben in diesem Thread. Angenommen, wir haben eine Zeichenkette in Anführungszeichen: 'A '\''B'\'' C' (alle Anführungszeichen hier sind einfache Anführungszeichen). Wenn es an echo übergeben wird, gibt es Folgendes aus: A 'B' C . In jedem '\'' das erste Anführungszeichen schließt die aktuelle Zeichenkette in einfachen Anführungszeichen ab, die folgende \' klebt ein einfaches Anführungszeichen an die vorherige Zeichenkette ( \' ist eine Möglichkeit, ein einfaches Anführungszeichen anzugeben, ohne eine Zeichenkette in Anführungszeichen zu beginnen), und das letzte Anführungszeichen öffnet eine weitere Zeichenkette in einfachen Anführungszeichen.

3 Stimmen

Dies ist irreführend, denn die Syntax '\'' geht nicht "innerhalb" einer einzelnen Anführungszeichenfolge. In dieser Anweisung 'A '\''B'\'' C' werden 5 Zeichenfolgen mit Escape-Zeichen und einfachen Anführungszeichen aneinandergereiht.

1 Stimmen

@teknopaul Der Auftrag alias something='A '\''B'\'' C' führt zu something da es sich um eine einzelne Zeichenkette handelt. Auch wenn die rechte Seite der Zuweisung technisch gesehen keine einzelne Zeichenkette ist, glaube ich nicht, dass dies von großer Bedeutung ist.

2 Stimmen

Dies funktioniert zwar in Ihrem Beispiel, ist aber nicht technisch Bereitstellung einer Lösung für das Einfügen eines einfachen Anführungszeichens innerhalb eine einzelne Zeichenkette in Anführungszeichen. Sie haben es bereits erklärt, aber ja, es macht 'A ' + ' + 'B' + ' + ' C' . Mit anderen Worten, eine Lösung für das Einfügen von einfachen Anführungszeichen innerhalb einer Zeichenkette mit einfachen Anführungszeichen sollte es mir ermöglichen, eine solche Zeichenkette selbst zu erstellen und sie zu drucken. Diese Lösung funktioniert jedoch in diesem Fall nicht. STR='\''; echo $STR . So wie es konzipiert ist, lässt BASH dies nicht wirklich zu.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X