So umgehen Sie einfache Anführungszeichen in Zeichenfolgen mit einfachen Anführungszeichen

StackOverflow https://stackoverflow.com/questions/1250079

  •  12-09-2019
  •  | 
  •  

Frage

Nehmen wir an, Sie haben einen Bash alias wie:

alias rxvt='urxvt'

was gut funktioniert.

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 am Ende öffnende und schließende Anführungszeichen innerhalb einer Zeichenfolge zusammenbringen, wenn Sie Anführungszeichen mit Escapezeichen versehen haben?

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

scheint unhandlich, obwohl es dieselbe Zeichenfolge darstellen würde, wenn Sie sie auf diese Weise verketten dürften.

War es hilfreich?

Lösung

Wenn Sie wirklich einfache Anführungszeichen in der äußersten Schicht verwenden möchten, denken Sie daran, dass Sie beide Arten von Anführungszeichen kleben kann. Beispiel:

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

Erläuterung, wie '"'"' als nur ' interpretiert:

  1. ' End erstes Zitat, das einfache Anführungszeichen verwendet.
  2. " starten zweites Zitat, Anführungszeichen verwenden.
  3. ' Zitat Charakter.
  4. " End zweites Zitat, Anführungszeichen verwenden.
  5. ' starten drittes Zitat, einfache Anführungszeichen verwenden.

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

Andere Tipps

ich immer ersetzen Sie einfach jedes eingebetteten Apostroph mit der Sequenz: '\'' (das heißt: Zitat Backslash Zitat Zitat), die die Zeichenfolge schließt, fügt einen entflohenen Apostroph und öffnet wieder die Zeichenfolge.


ich Peitsche oft eine „quotify“ -Funktion in meinem Perl-Skripte für mich, dies zu tun. Die Schritte wären:

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

Dieses ziemlich kümmert sich um alle Fälle.

Das Leben wird mehr Spaß, wenn man eval in der Shell-Skripte einführen. Sie müssen im Wesentlichen wieder quotify alles wieder!

Zum Beispiel erstellen Sie einen Perl-Skript namens quotify die obigen Aussagen enthalten:

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

verwendet es dann eine richtig zitierte Zeichenfolge zu generieren:

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

Ergebnis:

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

was kann dann Kopieren / Einfügen in den Alias-Befehl:

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

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

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

Ergebnis:

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

, das Kopieren / Einfügen in ein eval sein kann:

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

Da Bash 2,04 Syntax $'string' (statt nur 'string'; Warnung: nicht verwechseln mit $('string')) ist ein weiterer Mechanismus, der unter Angabe ANSI C-like-Escape-Sequenzen ermöglicht und Expansion zu tun Einzel zitierte Version.

Einfaches Beispiel:

  $> 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'\'''

Gemeinsame entweichende Sequenzen wie erwartet funktioniert:

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

Im Folgenden finden Sie Kopie + eingefügt bezogene Dokumentation von man bash (Version 4.4):

Worte der Form $ 'String' sind speziell behandelt. Das Wort expandiert zu bespannen, mit Backslash-Escape-Zeichen wie angegeben durch den Standard ANSI C ersetzt. Backslash Escape-Sequenzen, falls vorhanden, decodiert werden, wie folgt:

    \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 ist in einfachen Anführungszeichen, als ob das Dollarzeichen nicht anwesend war.


Siehe Zitate und Flucht: ANSI C wie Strings auf bash-Hacker. org Wiki für weitere Informationen. Beachten Sie auch, dass "Bash Changes" Datei ( Übersicht hier ) erwähnt eine Menge für Änderungen und Fehlerbehebung im Zusammenhang mit dem $'string' Quoting-Mechanismus.

Nach unix.stackexchange.com wie ein Sonderzeichen als ein normales benutzen? sollte es (mit einigen Variationen) in bash arbeiten, zsh, mksh, ksh93 und FreeBSD und busybox sh.

Ich sehe nicht, den Eintrag auf seinem Blog (Link pls?), Sondern nach dem Gnu-Referenzhandbuch :

  

Enclosing Zeichen in einfachen Anführungszeichen   ( ‚'‘) Bewahrt den wörtlichen Wert   jedes Zeichen innerhalb der Anführungszeichen. EIN   Apostroph kann nicht auftreten, zwischen   Apostrophe, selbst wenn sie durch ein voran   Backslash.

so bash nicht verstehen:

alias x='y \'z '

Sie können jedoch dies tun, wenn Sie mit doppelten Anführungszeichen:

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

kann ich bestätigen, dass ein Apostroph in einem einfachen Anführungszeichen Zeichenfolge funktioniert in Bash mit '\'', und es kann auf die gleiche Weise wie das „Kleben“ Argument von oben in dem Thread erläutert. Angenommen, wir haben eine Zeichenfolge in Anführungszeichen: 'A '\''B'\'' C' (alle hier Zitate sind einfache Anführungszeichen). Wenn es übergeben wird Echo, druckt er die folgenden: A 'B' C. In jedem '\'' das erste Zitat den aktuellen Einzel zitierte Zeichenfolge, die folgenden \' Leimen ein Apostroph auf die vorherige Zeichenfolge schließt (\' ist ein Weg, um einen Apostroph, um anzugeben, ohne eine zitierte Zeichenfolge beginnend), und das letzte Zitat öffnet eine weiteren ein- String in Anführungszeichen.

Einfaches Beispiel von Zitaten in der Schale zu entkommen:

$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc

Es ist vollbracht durch die Fertigstellung einer (') bereits geöffnet, Stellens entkam ein (\'), dann eine andere Öffnung ('). Diese Syntax funktioniert für alle Befehle. Es ist sehr ähnlich Annäherung an die erste Antwort.

Beiden Versionen arbeiten entweder mit Verkettung durch die entwichene Apostroph-Zeichen (\ ‚), oder mit Verkettung von den einzelnen Anführungszeichen in doppelten Anführungszeichen gesetzt ("‘").

Der Autor der Frage gar nicht bemerkt, dass es ein zusätzliches Apostroph ( ') war am Ende seines letzten Flucht Versuchs:

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
           │         │┊┊|       │┊┊│     │┊┊│       │┊┊│
           └─STRING──┘┊┊└─STRIN─┘┊┊└─STR─┘┊┊└─STRIN─┘┊┊│
                      ┊┊         ┊┊       ┊┊         ┊┊│
                      ┊┊         ┊┊       ┊┊         ┊┊│
                      └┴─────────┴┴───┰───┴┴─────────┴┘│
                          All escaped single quotes    │
                                                       │
                                                       ?

Wie Sie im vorherigen schönen Stück ASCII / Unicode Kunst sehen können, flüchtete die letzte Apostroph (\ ‚) durch eine unnötige Apostroph folgt (‘). einen Syntax-Highlighter wie die in Notepad ++ mit sehr nützlich erweisen kann.

Das gleiche gilt für ein weiteres Beispiel, wie die folgenden:

alias rc='sed '"'"':a;N;$!ba;s/\n/, /g'"'"
alias rc='sed '\'':a;N;$!ba;s/\n/, /g'\'

Diese zwei schöne Beispiele von Alias-Namen zeigen in einem sehr komplizierten und verschleierten Art und Weise, wie eine Datei nach unten ausgekleidet werden kann. Das heißt, aus einer Datei mit vielen Zeilen, die Sie nur eine Zeile mit Komma und Leerzeichen zwischen den Inhalten der vorherigen Linien erhalten. Um Sinne des vorherigen Kommentar zu machen, ist das folgende ein Beispiel:

$ cat Little_Commas.TXT
201737194
201802699
201835214

$ rc Little_Commas.TXT
201737194, 201802699, 201835214

Ich gehe nicht speziell auf die Zitierproblematik ein, denn manchmal ist es einfach sinnvoll, einen alternativen Ansatz in Betracht zu ziehen.

rxvt() { urxvt -fg "#${1:-000000}" -bg "#${2:-FFFFFF}"; }

was Sie dann wie folgt aufrufen können:

rxvt 123456 654321

Die Idee ist, dass Sie dies jetzt ohne Anführungszeichen aliasen können:

alias rxvt='rxvt 123456 654321'

oder, wenn Sie das einschließen müssen # in allen Anrufen aus irgendeinem Grund:

rxvt() { urxvt -fg "${1:-#000000}" -bg "${2:-#FFFFFF}"; }

was Sie dann wie folgt aufrufen können:

rxvt '#123456' '#654321'

dann ist ein Alias ​​natürlich:

alias rxvt="rxvt '#123456' '#654321'"

(Ups, ich glaube, ich habe das Zitat irgendwie angesprochen :)

Ich verwende nur Shell-Codes .. z.B. \x27 oder \\x22 als anwendbar. Keine Hektik, jemals wirklich.

Da man nicht einfache Anführungszeichen innerhalb einzelner Strings in Anführungszeichen setzen, die einfachste und lesbare Option ist eine HEREDOC Zeichenfolge verwenden

command=$(cat <<'COMMAND'
urxvt -fg '#111111' -bg '#111111'
COMMAND
)

alias rxvt=$command

In dem obigen Code wird der HEREDOC zum cat Befehl gesendet, und der Ausgang dieses auf eine Variable über die Befehlssubstitutions notation $(..) zugeordnet

Setzen Sie einen Apostroph um die HEREDOC benötigt wird, da es in einem $() ist

IMHO die wirkliche Antwort ist, dass Sie nicht Apostrophe in einfachen Anführungszeichen entkommen.

Seine unmöglich.

Wenn wir davon ausgehen, wir bash verwenden.

Von bash Handbuch ...

Enclosing characters in single quotes preserves the literal value of each
character within the quotes.  A single quote may not occur
between single quotes, even when preceded by a backslash.

Sie müssen eine der anderen Saite Fluchtmechanismen verwenden "oder \

Es gibt nichts Magisches alias, die sie verwenden einfache Anführungszeichen verlangt.

Sowohl die folgenden Arbeiten in der Bash.

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

Diese \ wird mit dem Leerzeichen zu entkommen.

Es gibt auch nichts Magisches # 111111, die einfache Anführungszeichen erfordert.

Die folgenden Optionen erreicht das gleiche Ergebnis die beiden anderen Optionen, dass der rxvt alias wie erwartet funktioniert.

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

Sie können auch die lästigen # direkt entkommen

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

Die meisten dieser Antworten treffen auf den konkreten Fall über Sie fragen. bash-Befehle durch mehrere Schichten von Shell-Erweiterung zu zitieren, zB durch ssh, su -c, bash -c usw. Es gibt einen Kern primitive Es gibt einen allgemeinen Ansatz, dass ein Freund und ich habe entwickelt, das für beliebige ermöglicht, falls unter Angabe Sie benötigen Sie benötigen , hier in nativer bash:

quote_args() {
    local sq="'"
    local dq='"'
    local space=""
    local arg
    for arg; do
        echo -n "$space'${arg//$sq/$sq$dq$sq$dq$sq}'"
        space=" "
    done
}

Das ist genau das, was er sagt: es muschel Anführungszeichen jedes Argument einzeln (nach bash Expansion, natürlich):

$ quote_args foo bar
'foo' 'bar'
$ quote_args arg1 'arg2 arg2a' arg3
'arg1' 'arg2 arg2a' 'arg3'
$ quote_args dq'"'
'dq"'
$ quote_args dq'"' sq"'"
'dq"' 'sq'"'"''
$ quote_args "*"
'*'
$ quote_args /b*
'/bin' '/boot'

Es macht die offensichtliche Sache für eine Schicht Expansion:

$ bash -c "$(quote_args echo a'"'b"'"c arg2)"
a"b'c arg2

(Beachten Sie, dass die doppelten Anführungszeichen um $(quote_args ...) notwendig sind, um das Ergebnis in ein einziges Argument zu machen bash -c.) Und es kann allgemein verwendet wird richtig durch mehrere Schichten von Expansion zu zitieren:

$ bash -c "$(quote_args bash -c "$(quote_args echo a'"'b"'"c arg2)")"
a"b'c arg2

Das obige Beispiel:

  1. muschel Anführungszeichen jedes Argument zu der inneren quote_args einzeln und kombiniert dann die resultierende Ausgabe in ein einziges Argument mit den inneren Anführungszeichen.
  2. Shell-Zitate bash, -c und das schon einmal zitierte Ergebnis aus Schritt 1, und dann das Ergebnis in ein einziges Argument kombiniert mit den äußeren Anführungszeichen gesetzt werden.
  3. sendet dieses Chaos als Argument an die äußere bash -c.

Das ist die Idee auf den Punkt gebracht. Sie können mit diesem ein paar ziemlich komplizierten Dingen tun, aber man muss vorsichtig sein, um die Bewertung und über den Teil notiert ist. So bauen Sie die falschen Dinge (für einige Definition von „falsch“):

$ (cd /tmp; bash -c "$(quote_args cd /; pwd 1>&2)")
/tmp
$ (cd /tmp; bash -c "$(quote_args cd /; [ -e *sbin ] && echo success 1>&2 || echo failure 1>&2)")
failure

Im ersten Beispiel dehnt sich sofort bash quote_args cd /; pwd 1>&2 in zwei getrennte Befehle, quote_args cd / und pwd 1>&2, so dass die CWD ist noch, wenn der /tmp pwd Befehl ausgeführt wird. Das zweite Beispiel zeigt ein ähnliches Problem für Globbing. Tatsächlich tritt das gleiche grundlegende Problem bei allen bash Erweiterungen. Das Problem hierbei ist, dass ein Befehl Substitution keinen Funktionsaufruf ist. Es buchstäblich einen Bash-Skript ist zu bewerten und mit seinem Ausgang als Teil eines anderen Bash-Skript

Wenn Sie versuchen, einfach, um den Shell-Betreiber zu entkommen, werden Sie scheitern, weil die resultierende Zeichenfolge bash -c geben ist nur eine Folge von individuell-Strings in Anführungszeichen, die nicht dann als Operatoren interpretiert werden, die leicht zu sehen, wenn Sie Echo die Zeichenfolge, die übergeben worden wäre bash:

$ (cd /tmp; echo "$(quote_args cd /\; pwd 1\>\&2)")
'cd' '/;' 'pwd' '1>&2'
$ (cd /tmp; echo "$(quote_args cd /\; \[ -e \*sbin \] \&\& echo success 1\>\&2 \|\| echo failure 1\>\&2)")
'cd' '/;' '[' '-e' '*sbin' ']' '&&' 'echo' 'success' '1>&2' '||' 'echo' 'failure' '1>&2'

Das Problem hierbei ist, dass Sie über zitieren. Was Sie brauchen, ist für die Betreiber als Eingabe für den umschließenden bash -c unquoted werden, was bedeutet, sie brauchen außerhalb des $(quote_args ...) Befehl Substitution sein.

Was folglich müssen Sie im allgemeinsten Sinne zu tun ist, zu Shell-Zitat jedes Wort des Befehls nicht beabsichtigt, separat zum Zeitpunkt der Kommandosubstitution erweitert werden und gilt keine zusätzliche Angabe der Shell Operatoren:

$ (cd /tmp; echo "$(quote_args cd /); $(quote_args pwd) 1>&2")
'cd' '/'; 'pwd' 1>&2
$ (cd /tmp; bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")
/
$ (cd /tmp; echo "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")
'cd' '/'; [ -e *'sbin' ] && 'echo' 'success' 1>&2 || 'echo' 'failure' 1>&2
$ (cd /tmp; bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")
success

Sobald Sie dies getan haben, die gesamte Zeichenfolge ist faires Spiel für die weitere Angabe zu beliebigen Ebenen der Auswertung:

$ bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")"
/
$ bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")")"
/
$ bash -c "$(quote_args bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")")")"
/
$ bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")"
success
$ bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *sbin ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")")"
success
$ bash -c "$(quote_args bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")")")"
success

etc.

mögen Diese Beispiele overwrought gegeben, dass Worte wie success, sbin und pwd müssen nicht seine muschel zitiert, aber der entscheidende Punkt zu erinnern, wenn ein Skript unter beliebiger Eingabe zu schreiben ist, dass man Ihnen zitieren will alles‘ re nicht absolut sicher nicht müssen zitieren, weil Sie nie wissen, wenn ein Benutzer in einem Robert'; rm -rf / werfen.

Um besser zu verstehen, was unter der Decke vor sich geht, können Sie mit zwei kleinen Helferfunktionen spielen, um:

debug_args() {
    for (( I=1; $I <= $#; I++ )); do
        echo -n "$I:<${!I}> " 1>&2
    done
    echo 1>&2
}

debug_args_and_run() {
    debug_args "$@"
    "$@"
}

, die jedes Argument auf einen Befehl aufzählen, bevor es ausgeführt wird:

$ debug_args_and_run echo a'"'b"'"c arg2
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)"
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")"
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")")"
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'echo'"'"' '"'"'a"b'"'"'"'"'"'"'"'"'c'"'"' '"'"'arg2'"'"''> 
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")")")"
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'bash'"'"' '"'"'-c'"'"' '"'"''"'"'"'"'"'"'"'"'debug_args_and_run'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'echo'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'a"b'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'c'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'arg2'"'"'"'"'"'"'"'"''"'"''> 
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'echo'"'"' '"'"'a"b'"'"'"'"'"'"'"'"'c'"'"' '"'"'arg2'"'"''> 
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

In dem gegebenen Beispiel einfach doppelte Anführungszeichen statt einfache Anführungszeichen als äußereer Fluchtmechanismus verwendet:

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

Dieser Ansatz für viele Fälle geeignet ist, wo man nur eine feste Zeichenfolge an einen Befehl übergeben werden soll. Stellt sicher, wie die Shell die Strings in doppelten Anführungszeichen durch eine echo interpretieren, und Escape-Zeichen mit Backslash falls erforderlich

In dem Beispiel, würden Sie sehen, dass doppelte Anführungszeichen ausreichend sind, um die Zeichenfolge zu schützen:

$ echo "urxvt -fg '#111111' -bg '#111111'"
urxvt -fg '#111111' -bg '#111111'

Hier ist eine Ausarbeitung über die einzig wahre Antwort oben zitiert:

Manchmal werde ich rsync über ssh verwenden werden, das Herunterladen und einen Dateinamen mit einem "darin ZWEIMAL entkommen müssen! (OMG!) Einmal für bash und einmal für ssh. Das gleiche Prinzip des Begrenzer Zitat abwechselnd ist bei der Arbeit hier.

Zum Beispiel, sagen wir, wir erhalten möchten: Louis Theroux LA Geschichten ...

  1. Zuerst Louis Theroux in einfache Anführungszeichen für bash und doppelte Anführungszeichen für ssh einschließen: ' "Louis Theroux"'
  2. Dann nutzen Sie einfache Anführungszeichen ein Anführungszeichen " 'zu entkommen
  3. Die Verwendung doppelte Anführungszeichen den Apostroph „'“
  4. zu entkommen
  5. Wiederholen Sie dann die # 2, einfache Anführungszeichen mit einem doppelten Anführungszeichen zu entkommen " '
  6. umschließen Dann LA Geschichten in einfache Anführungszeichen für bash und doppelte Anführungszeichen für ssh: ' "LA Stories"'

Und siehe! Sie aufzuwickeln mit diesem:

rsync -ave ssh '"Louis Theroux"''"'"'"'"''"s LA Stories"'

, die für ein wenig schrecklich viel Arbeit ist "- aber dort gehen Sie

Eine andere Möglichkeit, das Problem der zu viele Schichten von verschachtelten Anführungszeichen zu beheben:

Sie versuchen, zu viel in zu winzig einen Raum zu stopfen, so eine Bash-Funktion verwenden.

Das Problem ist, dass Sie versuchen, zu viele Ebenen der Verschachtelung und der Grund Alias-Technologie ist nicht stark genug, um gerecht zu werden. Verwenden Sie wie folgt ein Bash-Funktion, um es so die einzelnen, doppelten Anführungszeichen Ticks zurück und übergeben Parameter werden alle behandelt normalerweise als würden wir erwarten:

lets_do_some_stuff() {
    tmp=$1                       #keep a passed in parameter.
    run_your_program $@          #use all your passed parameters.
    echo -e '\n-------------'    #use your single quotes.
    echo `date`                  #use your back ticks.
    echo -e "\n-------------"    #use your double quotes.
}
alias foobarbaz=lets_do_some_stuff

Dann können Sie Ihre $ 1 und $ 2 Variablen und einzelne, doppelte Anführungszeichen verwenden und Zecken zurück, ohne ihre Integrität sich Gedanken über die Alias-Funktion Wrecking.

Dieses Programm druckt:

el@defiant ~/code $ foobarbaz alien Dyson ring detected @grid 10385
alien Dyson ring detected @grid 10385
-------------
Mon Oct 26 20:30:14 EDT 2015
-------------
shell_escape () {
    printf '%s' "'${1//\'/\'\\\'\'}'"
}

Implementierung Erklärung:

  • doppelte Anführungszeichen so können wir leicht Ausgabeverpackung einfache Anführungszeichen und verwenden Sie die ${...} Syntax

  • bash Suchen und Ersetzen sieht aus wie: ${varname//search/replacement}

  • ersetzen wir ' mit '\''

  • '\'' kodiert für ein einzelnes ' etwa so:

    1. ' endet die einzige Angabe

    2. \' codiert ein ' (der Schrägstrich ist erforderlich, weil wir nicht in Anführungszeichen sind)

    3. ' startet einzelne zitieren wieder

    4. bash automatisch verkettet Strings ohne Leerzeichen zwischen

  • gibt es eine \ vor jedem \ und ' denn das ist die Escape-Regeln für ${...//.../...} ist.

string="That's "'#@$*&^`(@#'
echo "original: $string"
echo "encoded:  $(shell_escape "$string")"
echo "expanded: $(bash -c "echo $(shell_escape "$string")")"

P. S. Immer kodieren Strings in Anführungszeichen, einzelne, weil sie Art und Weise einfacher als das doppelte Anführungszeichen sind.

Wenn Sie GNU Parallel installiert Sie verwenden können, ihre internen zitiert:

$ parallel --shellquote
L's 12" record
<Ctrl-D>
'L'"'"'s 12" record'
$ echo 'L'"'"'s 12" record'
L's 12" record

Ab Version 20190222 Sie können sogar --shellquote mehrfach:

$ parallel --shellquote --shellquote --shellquote
L's 12" record
<Ctrl-D>
'"'"'"'"'"'"'L'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'s 12" record'"'"'"'"'"'"'
$ eval eval echo '"'"'"'"'"'"'L'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'s 12" record'"'"'"'"'"'"'
L's 12" record

Es wird die Zeichenkette in allen unterstützten Schalen zitieren (nicht nur bash).

Diese Funktion:

quote () 
{ 
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

können von ' innerhalb ' zitieren. Verwenden Sie wie folgt aus:

$ quote "urxvt -fg '#111111' -bg '#111111'"
'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

Wenn die Zeile Zitat komplexer wird, wie doppelte Anführungszeichen mit einfachen Anführungszeichen gemischt, kann es ziemlich schwierig geworden, die Zeichenfolge zu bekommen innerhalb einer Variablen zu zitieren. Wenn solche Fälle auftauchen, schreiben die genaue Zeile, die Sie benötigen innerhalb eines Skripts (ähnlich wie diese) zu zitieren.

#!/bin/bash

quote ()
{
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

while read line; do
    quote "$line"
done <<-\_lines_to_quote_
urxvt -fg '#111111' -bg '#111111'
Louis Theroux's LA Stories
'single quote phrase' "double quote phrase"
_lines_to_quote_

Will Ausgabe:

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
'Louis Theroux'\''s LA Stories'
''\''single quote phrase'\'' "double quote phrase"'

Alle korrekt Strings in Anführungszeichen in einfache Anführungszeichen.

Natürlich wäre es einfacher, einfach zu sein, mit doppelten Anführungszeichen zu umgeben, aber wo ist die Herausforderung darin? Hier ist die Antwort nur einfache Anführungszeichen verwenden. Ich bin statt alias eine Variable, so dass es einfacher ist für Beweis zu drucken, aber es ist die gleiche wie alias verwendet wird.

$ rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'
$ echo $rxvt
urxvt -fg '#111111' -bg '#111111'

Erklärung

Der Schlüssel ist, dass Sie das Apostroph schließen und wieder öffnen, so oft wie Sie wollen. Zum Beispiel foo='a''b' ist die gleiche wie foo='ab'. So ermitteln Sie den Apostroph schließen können, in einem wörtlichen Apostroph \' wirft, dann die nächste Apostroph wieder öffnen.

Pannen Diagramm

Dieses Diagramm macht deutlich, durch Klammern zu zeigen, wo die einfachen Anführungszeichen geöffnet und geschlossen werden. Zitate sind nicht „verschachtelt“ wie Klammern sein können. Sie können auch auf die farbliche Hervorhebung zahlen, die richtig angewendet wird. Die Anführungszeichen sind kastanienbraun, während die \' schwarz ist.

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'    # original
[^^^^^^^^^^] ^[^^^^^^^] ^[^^^^^] ^[^^^^^^^] ^    # show open/close quotes
 urxvt -fg   ' #111111  '  -bg   ' #111111  '    # literal characters remaining

(Dies ist im Wesentlichen die gleiche Antwort wie Adrians, aber ich finde, dass das erklärt es besser. Auch seine Antwort hat 2 überflüssig einfache Anführungszeichen am Ende.)

Hier ist eine andere Lösung. Diese Funktion wird ein einziges Argument nehmen und zitieren sie in geeigneter Weise die einzelnen Anführungszeichen verwenden, ebenso wie die Abstimmung Antwort oben erklärt:

single_quote() {
  local quoted="'"
  local i=0
  while [ $i -lt ${#1} ]; do
    local ch="${1:i:1}"
    if [[ "$ch" != "'" ]]; then
      quoted="$quoted$ch"
    else
      local single_quotes="'"
      local j=1
      while [ $j -lt ${#1} ] && [[ "${1:i+j:1}" == "'" ]]; do
        single_quotes="$single_quotes'"
        ((j++))
      done
      quoted="$quoted'\"$single_quotes\"'"
      ((i+=j-1))
    fi
    ((i++))
  done
  echo "$quoted'"
}

So können Sie es auf diese Weise verwendet werden:

single_quote "1 2 '3'"
'1 2 '"'"'3'"'"''

x="this text is quoted: 'hello'"
eval "echo $(single_quote "$x")"
this text is quoted: 'hello'

Wenn Sie die Shell-Zeichenfolge in Python 2 oder Python 3 sind zu erzeugen, die folgende kann helfen, die Argumente zu zitieren:

#!/usr/bin/env python

from __future__ import print_function

try:  # py3
    from shlex import quote as shlex_quote
except ImportError:  # py2
    from pipes import quote as shlex_quote

s = """foo ain't "bad" so there!"""

print(s)
print(" ".join([shlex_quote(t) for t in s.split()]))

Dies wird ausgegeben:

foo ain't "bad" so there!
foo 'ain'"'"'t' '"bad"' so 'there!'
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top