2010-09-30 142 views
147

任何人都可以告诉我如何在bash中双字符串内部双引号转义?如何摆脱双引号内的双引号?

举例来说,在我的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" 

我不能让用双引号逃逸ENCLOSED BY \"正确。我不能为我的变量使用单引号,因为我想使用变量$dbtable

+45

你应该熟悉[SQL注入](HTTP的概念:// EN。 wikipedia.org/wiki/SQL_injection),然后再开始编写这样的代码。 – Daenyth 2010-09-30 21:10:22

+1

另请参阅http://mywiki.wooledge.org/BashFAQ/050 – 2013-11-13 13:38:25

+0

[单引号字符串内转义单引号]的可能重复(http://stackoverflow.com/questions/1250079/escaping-single-quotes-单引号内的字符串) – kenorb 2015-02-28 20:50:54

回答

170

使用反斜线:

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

不工作。 'X = LS; if [-f“$(which”\“”$ x“\”“)”];那么回声存在;否则回声破碎; fi;'给破了,而'... [-f“$(which $ x)”]; ...'或'... [-f $(其中“$ x”)]; ......工作很好。当'$ x'或'$(其中“$ x”)'给出任何空格或其他特殊字符的结果时都会出现问题。解决方法是使用一个变量来保存'which'的结果,但是bash真的无法逃避报价或者我做错了什么? – Luc 2015-07-27 15:10:50

+0

我试图使用下面的'grep -oh“\”\“”$ counter“\”“\ w *”'作为bash语法的一部分,其中'$ counter'是一个变量。它不喜欢它的任何想法 – 2015-12-18 00:30:39

10

退房的printf ...

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

没有用printf

echo -e $mystr 

输出:说 “嗨”

使用的printf

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

输出:说\ “喜\”

+1

请注意,'printf'也会转义更多字符,例如'''','('和')' – 2013-05-10 10:14:21

+0

'printf%q'生成准备用于'eval'的字符串,未格式化为'echo -e'。 – 2013-11-13 13:38:00

+2

没有理由将[printf]封装成[无用的'echo'](http://www.iki.fi/era/unix/award.html#echo)。你的两个例子都被打破了引用。正确的解决方法是双引号变量。 – tripleee 2017-03-16 06:33:21

35

逃逸壳报价的简单的例子:

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

它由精加工已经打开了一个(')来完成,放置一个(\'),然后打开另一个(')。

或者:

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

它由精加工已经打开了一个(')完成后,将报价在另一个引号("'"),然后打开另一个(')。

更多的例子:Escaping single-quotes within single-quoted strings

+1

我试过sh -c“echo”{“key”:“value”}'“,甚至sh -c”echo'{'''''key''''':'''''value''“ ''}'“,试图用双引号括住单词key和值,但是在这两种情况下,我都得到了{key:value} – 2017-06-18 09:28:44

17

击可以让你把相邻的字符串,他们会刚刚结束了被粘在一起。

因此,这:

$ echo "Hello"', world!' 

产生

Hello, world! 

诀窍是根据需要单和双引号字符串之间交替。不幸的是,它很快变得非常混乱。例如:

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

产生

​​

在你的榜样,我会做这样的事情:

$ 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 

产生以下的输出:

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

这是很难看到这里发生了什么,但我可以使用Unicode引号标注。下面将不会在bash工作 - 它只是为了说明:

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

上面的“''”等引号将被bash解释。像" '这样的引号最终会出现在结果变量中。

如果我给同等待遇,以前面的例子,它看起来像这样:

$ echoI like to use"double quotes"sometimes

3

。利用$ “字符串” 的。

在这个例子中,那将是,

dbload = $ “负荷数据本地的infile \” 'gfpoint.csv' \”到TERMINATED BY表$ DBTABLE场 '' ENCLOSED BY“\” 'LINES TERMINATED BY \ “ '\ n' \” 忽略1号线”

注(从man page):

一个美元符号($开头的双引号字符串 “字符串” )将导致字符串被转换到当前的语言环境。如果当前区域设置为C或POSIX,则忽略美元符号。如果字符串被翻译并替换,则替换为双引号。

-4

双引号逃跑之前添加"\",而不是\

#! /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:你为什么在'bash'问题上发布'csh'答案?这两者完全不同并且不兼容。 – tripleee 2017-03-16 06:35:36

20

我不知道为什么这个老问题今天突然出现在bash的标签列表,但以防万一对未来的研究人员,请记住,您可以通过使用需要回显的字符的ascii代码来避免转义。 实施例:

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

\x22为单引号为双引号的ASCII码(十六进制),并\x27。同样,你可以回显任何字符。

我想,如果我们试图以呼应上述字符串反斜杠,我们需要一个混乱的两排反斜线的回声...... :)

为变量赋值,这是等价的:

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

如果这个变量已经被其他程序设置了,你仍然可以用sed或者类似的工具应用双引号。 例子:

$ 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因为它解决了为〜/ .profile添加PS1变量的问题 'echo'export PS1 ='\ [\ 033 [00; 31m \] $ {?## 0} $([$? -01 0] && echo \ x22 \ x22)\ [\ 033 [00; 32m \] \ u \ [\ 033 [00; \] @ \ [\ 033 [00; 36m \] \ h \ [\ \ [0; 0] [\ 0 [0; 0] [\ 033 [00m \] $( [$ {EUID} -ne 0] && echo \ x22 $ \ x22 || echo \ x22#\ x22)''〜〜/ .profile' – 2017-04-18 05:19:12

+2

这应该可能被标记为答案。 – qodeninja 2017-12-21 18:27:23

3

商店双引号字符作为变量:

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

输出:

 
Double quotes "X" inside a double quoted string