2010-09-30 7 views
147

Quelqu'un peut-il me montrer comment échapper à double guillemet à l'intérieur d'une double chaîne de bash?Comment échapper un guillemet entre guillemets?

Par exemple, dans mon script shell

#!/bin/bash 

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

Je ne peux pas ENCLOSED BY \" avec guillemet évasion correctement. Je ne peux pas utiliser guillemet simple pour ma variable parce que je veux utiliser la variable $dbtable.

+45

Vous devez vous familiariser avec le concept de [injection sql] (http: // fr. wikipedia.org/wiki/SQL_injection) avant de commencer à écrire du code comme celui-ci. – Daenyth

+1

Voir également http://mywiki.wooledge.org/BashFAQ/050 –

+0

duplication possible de [Échapper des guillemets simples dans les guillemets simples] (http://stackoverflow.com/questions/1250079/escaping-single-quotes- within-single-quoted-strings) – kenorb

Répondre

170

Utilisez une barre oblique inverse:

echo "\""  # Prints one " character. 
+3

Ne fonctionne pas. 'x = ls; if [-f "$ (dont" \ "" $ x "\" ")"]; alors l'écho existe; sinon l'écho est brisé; fi; 'donne cassé alors que ... ... -f" $ (dont $ x) "]; ... 'ou' ... [-f $ (dont "$ x")]; ... 'fonctionne très bien. Des problèmes surgiraient lorsque soit '$ x' ou le résultat de' $ (où "$ x") 'donne quelque chose avec un espace ou un autre caractère spécial. Une solution de contournement utilise une variable pour contenir le résultat de 'which', mais bash est vraiment incapable d'échapper une citation ou est-ce que je fais quelque chose de mal? – Luc

+0

J'essaie d'utiliser le 'grep -oh" \ "\" "$ counter" \ "" \ w * "' dans le cadre d'une syntaxe bash où '$ counter 'est une variable. –

10

départ printf ...

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

Sans utiliser printf

echo -e $mystr 

sortie: dire "salut"

En utilisant printf

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

sortie: dire \ "salut \"

+1

Notez que 'printf' échappe aussi plus de caractères, comme' '', '' '' '' '' '' '' '' '' '' '' '' '' –

+0

'printf% q' génère des chaînes prêtes pour' eval', non formatées pour 'echo -e'. –

+2

Il n'y a aucune raison d'envelopper 'printf' avec une [utilisation inutile de' echo'] (http://www.iki.fi/era/unix/award.html#echo). Vos deux exemples ont cassé la citation. Le correctif approprié consiste à double-citation de la variable. – tripleee

35

Exemple simple d'échapper à des citations décortiqués:

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

Il est fait par finition déjà ouvert un ('), placer un échappement (\'), puis en ouvrir un autre (').

Autre possibilité:

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

Il est fait en terminant déjà ouvert un ('), placer citation dans une autre citation ("'"), puis en ouvrir une autre (').

Autres exemples: Escaping single-quotes within single-quoted strings

+1

J'ai essayé sh -c "echo '{" clé ":" valeur "}'" et même sh -c "echo '{' '"' 'key' '"' ':' '"' 'valeur' ​​'" ''} '"dans le but d'entourer les mots clé et valeur entre guillemets, mais dans les deux cas j'ai reçu {clé: valeur} –

17

Bash vous permet de placer des chaînes de manière adjacente, et ils vont finir par être collées ensemble.

donc ceci:

$ echo "Hello"', world!' 

produit

Hello, world! 

L'astuce consiste à alterner entre les cordes simples et doubles guillemets, au besoin. Malheureusement, il devient rapidement très salissant.Par exemple:

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

produit

I like to use "double quotes" sometimes 

Dans votre exemple, je ferais quelque chose comme ceci:

$ 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 

qui produit la sortie suivante:

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

Il est difficile de voir ce qui se passe ici, mais je peux l'annoter à l'aide des citations Unicode. Ce qui suit ne marchera pas dans bash - il est juste pour illustration:

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

Les citations comme "'" dans ce qui précède seront interprétées par bash. Les citations comme " ' finiront dans la variable résultante.

Si je donne le même traitement à l'exemple précédent, il ressemble à ceci:

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

3

Faire usage de "string" $.

Dans cet exemple, il serait,

DBLoad = $ "charge des données infile locales \" 'gfpoint.csv \ » dans la table $ DBTABLE FIELDS TERMINATED BY '' ENCLOSED BY « \ » 'LINES TERMINATED BY \ "\ n" \" IGNORE 1 LIGNES »

note (du man page):

une chaîne entre guillemets précédée d'un signe de dollar ($ "string") provoquera la traduction de la chaîne selon à la locale actuelle. Si l'environnement local actuel est C ou POSIX, le signe dollar est ignoré. Si la chaîne est traduite et remplacée, le remplacement est entre guillemets.

-4

ajouter "\" avant guillemet pour y échapper, au lieu de \

#! /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 
+2

Downvote: Pourquoi publiez-vous une réponse' csh' à une question 'bash'? Les deux sont complètement distincts et incompatibles. – tripleee

20

Je ne sais pas pourquoi ce vieux problème surgit aujourd'hui dans le bash annonces marqué, mais juste au cas où pour les futurs chercheurs , gardez à l'esprit que vous pouvez éviter d'échapper en utilisant les codes ascii des caractères que vous avez besoin d'écho. Exemple:

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

\x22 est le code ascii (en hexadécimal) pour des guillemets doubles et \x27 pour des guillemets simples. De même, vous pouvez faire écho à n'importe quel caractère.

Je suppose que si nous essayons de faire écho la chaîne ci-dessus avec des barres obliques inverses, nous aurons besoin de deux lignes en désordre backslashés écho ... :)

Pour l'affectation des variables ceci est l'équivalent:

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

Si la variable est déjà définie par un autre programme, vous pouvez toujours appliquer des guillemets doubles/simples avec sed ou des outils similaires. Exemple:

$ 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. 
+0

+1 parce qu'il a résolu le problème de l'ajout d'une variable PS1 à ~/.profile 'echo 'exporter 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' –

+2

cela devrait probablement être marqué comme la réponse. – qodeninja

3

Conserver le guillemet comme variable:

 
dqt='"' 
echo "Double quotes ${dqt}X${dqt} inside a double quoted string" 

Sortie:

 
Double quotes "X" inside a double quoted string 
Questions connexes