Wie kann ich einem doppelten Anführungszeichen in doppelten Anführungszeichen entkommen?

286

Wie kann ich doppelte Anführungszeichen in einer doppelten Zeichenfolge in Bash umgehen?

Zum Beispiel in meinem Shell-Skript

#!/bin/bash

dbload="load data local infile \"'gfpoint.csv'\" into table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY \"'\n'\" IGNORE 1 LINES"

Ich kann das ENCLOSED BY '\"'mit doppeltem Anführungszeichen nicht richtig entkommen lassen. Ich kann keine einfachen Anführungszeichen für meine Variable verwenden, da ich eine Variable verwenden möchte $dbtable.

Sean Nguyen
quelle
1
Siehe auch mywiki.wooledge.org/BashFAQ/050
Charles Duffy
2
@kenorb Sieht nicht aus wie ein Duplikat dieser Frage ...
Mark
@Daenyth Dies ist nicht die Art von Befehl, auf die Endbenutzer Zugriff haben sollen. Massenladeskripte werden normalerweise von vertrauenswürdigen Benutzern (z. B. Systemadministratoren oder Entwicklern) auf dem Server ausgeführt. Ja, wenn Endbenutzer den Wert von kontrollieren $dbtable, besteht ein Risiko. Dies wäre jedoch sehr ungewöhnlich, da Endbenutzer normalerweise kein SSH auf einen Computer ausführen, um ihre Daten zu laden.
jpmc26

Antworten:

285

Verwenden Sie einen Backslash:

echo "\""     # Prints one " character.
Peter
quelle
9
Funktioniert nicht. x=ls; if [ -f "$(which "\""$x"\"")" ]; then echo exists; else echo broken; fi;gibt kaputt wohingegen ... [ -f "$(which $x)" ]; ...oder ... [ -f $(which "$x") ]; ...funktioniert gut. Probleme würden auftreten, wenn entweder $xoder das Ergebnis von $(which "$x")etwas mit einem Leerzeichen oder einem anderen besonderen Charakter ergibt. Eine Problemumgehung verwendet eine Variable, um das Ergebnis von zu whichspeichern, aber ist bash wirklich nicht in der Lage, einem Zitat zu entkommen, oder mache ich etwas falsch?
Luc
Ich versuche, Folgendes grep -oh "\"\""$counter"\""\w*" als Teil einer Bash-Syntax zu verwenden, wobei in $countereine Variable ist. es mag es keine Gedanken
Jay D
82

Ein einfaches Beispiel für das Entkommen von Anführungszeichen in der Shell:

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

Dazu beenden Sie ein bereits geöffnetes ( '), platzieren das entkommene ( \') und öffnen dann ein weiteres ( ').

Alternative:

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

Dazu beenden Sie bereits geöffnetes ( '), setzen ein Zitat in ein anderes Zitat ( "'") und öffnen dann ein anderes ( ').

Weitere Beispiele: Escapezeichen in einfachen Anführungszeichen in Zeichenfolgen in einfachen Anführungszeichen

Kenorb
quelle
1
Ich habe versucht, sh -c "echo '{" key ":" value "}'" und sogar sh -c "echo '{' '"' 'key' '"' ':' '"' 'value' '"' '}' "in dem Bestreben, die Wörter Schlüssel und Wert in doppelte Anführungszeichen zu setzen, aber in beiden Fällen bekam ich {Schlüssel: Wert}
Igor Yagolnitser
1
Dies erscheint für doppelte Anführungszeichen unnötig kompliziert: Es echo "abc\"abc"reicht aus, um abc"abcwie in Peter Antwort zu produzieren.
Divenex
2
In diesem einfachen Beispiel, aber in komplexen Fällen verschachtelter Anführungszeichen, kann es notwendig sein, dies zu tun, und das Beispiel von @ kenorb hat mir geholfen, herauszufinden, wie ich mit diesen Fällen umgehen soll.
Prosoitos
63

Ich weiß nicht, warum dieses alte Problem heute in den mit Bash-Tags versehenen Listen aufgetaucht ist, aber denken Sie für den Fall zukünftiger Forscher daran, dass Sie die Flucht vermeiden können, indem Sie ASCII-Codes der Zeichen verwenden, die Sie wiederholen müssen.

Beispiel:

 echo -e "This is \x22\x27\x22\x27\x22text\x22\x27\x22\x27\x22"
 This is "'"'"text"'"'"

\x22ist der ASCII-Code (in hexadezimaler Schreibweise) für doppelte und \x27einfache Anführungszeichen. Ebenso können Sie jedes Zeichen wiedergeben.

Ich nehme an, wenn wir versuchen, die obige Zeichenfolge mit Backslashes wiederzugeben, benötigen wir ein unordentliches Backslashed-Echo mit zwei Zeilen ... :)

Für die Variablenzuweisung ist dies das Äquivalent:

 $ a=$'This is \x22text\x22'
 $ echo "$a"
 This is "text"

Wenn die Variable bereits von einem anderen Programm festgelegt wurde, können Sie mit sed oder ähnlichen Tools weiterhin doppelte / einfache Anführungszeichen anwenden.

Beispiel:

 $ b="Just another text here"
 $ echo "$b"
 Just another text here
 $ sed 's/text/"'\0'"/' <<<"$b" #\0 is a special sed operator
 Just another "0" here #this is not what i wanted to be
 $ sed 's/text/\x22\x27\0\x27\x22/' <<<"$b"
 Just another "'text'" here #now we are talking. You would normally need a dozen of backslashes to achieve the same result in the normal way.
George Vasiliou
quelle
1
+1, weil es ein Problem beim Hinzufügen einer PS1-Variablen zu ~ / .profileecho 'export PS1='\[\033[00;31m\]${?##0}$([ $? -ne 0 ] && echo \x22 \x22)\[\033[00;32m\]\u\[\033[00m\]@\[\033[00;36m\]\h\[\033[00m\][\[\033[01;33m\]\d \t\[\033[00m\]] \[\033[01;34m\]\w\n\[\033[00m\]$( [ ${EUID} -ne 0 ] && echo \x22$\x22 || echo \x22#\x22 ) '' >> ~/.profile
Yassine ElBadaoui
1
Das ist die Antwort! Ich liebe dich, Sir.
Miguel Rojas Cortés
28

Mit Bash können Sie Saiten nebeneinander platzieren, und sie werden einfach zusammengeklebt.

Also das:

$ echo "Hello"', world!'

produziert

Hello, world!

Der Trick besteht darin, je nach Bedarf zwischen einfachen und doppelten Zeichenfolgen zu wechseln. Leider wird es schnell sehr chaotisch. Beispielsweise:

$ echo "I like to use" '"double quotes"' "sometimes"

produziert

I like to use "double quotes" sometimes

In Ihrem Beispiel würde ich es ungefähr so ​​machen:

$ dbtable=example
$ dbload='load data local infile "'"'gfpoint.csv'"'" into '"table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '"'"'"' LINES "'TERMINATED BY "'"'\n'"'" IGNORE 1 LINES'
$ echo $dbload

welches die folgende Ausgabe erzeugt:

load data local infile "'gfpoint.csv'" into table example FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY "'\n'" IGNORE 1 LINES

Es ist schwer zu erkennen, was hier vor sich geht, aber ich kann es mit Unicode-Anführungszeichen kommentieren. Folgendes funktioniert in Bash nicht - es dient nur zur Veranschaulichung:

dbload=' load data local infile "' ' ' 'gfpoint.csv'' " into' table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '' "' ' LINES' TERMINATED BY "' '\n'' ' ' ' ' ' ' ' ' '" IGNORE 1 LINES ' '

Die Anführungszeichen wie "''" oben werden von bash interpretiert. Die Zitate mögen" ' werden in der resultierenden Variablen enden.

Wenn ich das vorherige Beispiel gleich behandle, sieht es so aus:

$ echo" I like to use" " "double quotes"" " sometimes"

Käfer
quelle
4
Oof ... das ist ein hässliches Zeug.
Magic Octopus Urn
17

Check out printf ...

#!/bin/bash
mystr="say \"hi\""

Ohne printf

echo -e $mystr

Ausgabe: Sag "Hallo"

Mit printf

echo -e $(printf '%q' $mystr)

Ausgabe: Sagen Sie "Hallo".

Danny Hong
quelle
2
Beachten Sie, dass printfmehr Zeichen als auch, wie entkommt ', (und)
David Pärsson
printf %qgeneriert Zeichenfolgen, die bereit sind eval, nicht formatiert sind echo -e.
Charles Duffy
2
Es gibt keinen Grund, das printfmit einer nutzlosen Verwendung vonecho zu verpacken . Ihre beiden Beispiele haben das Zitat gebrochen. Die richtige Lösung besteht darin, die Variable in doppelte Anführungszeichen zu setzen.
Tripleee
15

Speichern Sie das doppelte Anführungszeichen als Variable:

dqt = '"'
echo "Doppelte Anführungszeichen $ {dqt} X $ {dqt} in einer Zeichenfolge mit doppelten Anführungszeichen"

Ausgabe:

Doppelte Anführungszeichen "X" in einer Zeichenfolge in doppelten Anführungszeichen
12 Uhr
quelle
39
Bash ist wirklich die schlechteste Sprache
Andy Ray
@ 12oclocker, deine Antwort ist kinderleicht: D! Besonders bei Verwendung mit dem Befehl "sed" hat es mir den Tag gerettet!
Artanis Zeratul
11

Verwenden Sie $ "string".

In diesem Beispiel wäre es,

dbload = $ "lokale Datendatei" "gfpoint.csv" "in Tabelle $ dbtable laden.

Hinweis (von der Manpage ):

Eine Zeichenfolge in doppelten Anführungszeichen, der ein Dollarzeichen ($ "Zeichenfolge") vorangestellt ist, bewirkt, dass die Zeichenfolge gemäß dem aktuellen Gebietsschema übersetzt wird. Wenn das aktuelle Gebietsschema C oder POSIX ist, wird das Dollarzeichen ignoriert. Wenn die Zeichenfolge übersetzt und ersetzt wird, wird die Ersetzung in doppelte Anführungszeichen gesetzt.

Trisha Chatterjee
quelle
3
Schön, wusste das nicht.
David Kierans
-5

Fügen Sie "\"vor dem doppelten Anführungszeichen hinzu, um es zu umgehen, anstatt\

#! /bin/csh -f

set dbtable = balabala

set dbload = "load data local infile "\""'gfpoint.csv'"\"" into table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '"\""' LINES TERMINATED BY "\""'\n'"\"" IGNORE 1 LINES"

echo $dbload
# load data local infile "'gfpoint.csv'" into table balabala FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY "''" IGNORE 1 LINES
Shilv
quelle
6
Downvote: Warum postest du eine cshAntwort auf eine bashFrage? Die beiden sind völlig verschieden und inkompatibel.
Tripleee