如何对双引号中的双引号进行转义?

How can I escape a double quote inside double quotes?

提问人:Sean Nguyen 提问时间:10/1/2010 最后编辑:Peter MortensenSean Nguyen 更新时间:4/25/2023 访问量:579547

问:

如何在 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

Bash 行情

评论

1赞 Charles Duffy 11/13/2013
另请参阅 mywiki.wooledge.org/BashFAQ/050
0赞 kenorb 3/1/2015
在单引号字符串中转义单引号的可能重复项
5赞 Mark 10/26/2016
@kenorb 看起来不像是那个问题的重复......
0赞 tripleee 3/16/2017
另请参阅 stackoverflow.com/questions/10067266/...
0赞 jpmc26 12/20/2017
@Daenyth 这不是您希望最终用户有权访问的命令类型。大容量加载脚本通常由受信任的用户(如系统管理员或开发人员)服务器上运行。是的,如果最终用户控制了 的值,则存在风险。不过,这种情况非常罕见,因为最终用户通常不会通过 SSH 连接到计算机来加载他们的数据。$dbtable

答:

380赞 Peter 10/1/2010 #1

使用反斜杠:

echo "\""     # Prints one " character.

评论

17赞 Luc 7/27/2015
不工作。 给坏了,而或工作就好了。当任何一个或结果都给出任何带有空格或其他特殊字符的东西时,就会出现问题。一种解决方法是使用变量来保存 的结果,但是 bash 真的无法转义引号还是我做错了什么?x=ls; if [ -f "$(which "\""$x"\"")" ]; then echo exists; else echo broken; fi;... [ -f "$(which $x)" ]; ...... [ -f $(which "$x") ]; ...$x$(which "$x")which
0赞 Jay D 12/18/2015
我正在尝试使用以下内容作为 bash 语法的一部分,其中 in 是一个变量。它不喜欢它的任何想法grep -oh "\"\""$counter"\""\w*" $counter
4赞 AndroidEngineX 11/13/2021
嗨,你的方法不起作用。请删除您的答案,因为它可能已经浪费了很多有用的时间。正确答案是通过@kenorb您的答案仅在终端调用时有效,而不是在 bash 文件中无效。在发布(可能是剪切粘贴解决方案)之前,您自己尝试过吗 :( ?
1赞 Charles Duffy 9/8/2022
@AndroidEngineX,如果使用得当,此方法效果很好。Luc 上面的评论用错了;他们告诉要搜索名称中带有文字引号的可执行文件,当然不存在这样的东西。这是卢克自己的问题,而不是这个答案的错误。which
0赞 Charles Duffy 9/8/2022
@JayD,首先在POSIX标准中根本不起作用。它是 PCRE 扩展,grep 仅支持 BRE 和 ERE。在不知道您希望匹配哪些字符串/您如何测试的情况下,我无法评估您的评论。\wgrep
20赞 Danny Hong 10/31/2012 #2

查看 printf...

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

不使用 printf

echo -e $mystr

输出:说“嗨”

使用 printf

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

输出:说“嗨”

评论

2赞 David Pärsson 5/10/2013
请注意,还会转义更多字符,例如 和printf'()
0赞 Charles Duffy 11/13/2013
printf %q生成 ready for 的字符串,而不是格式化的 字符串。evalecho -e
3赞 tripleee 3/16/2017
没有理由用无用的回声来包装。你的两个例子都打破了引用。正确的解决方法是用双引号引起变量。printf
145赞 kenorb 3/1/2015 #3

在 shell 中转义引号的简单示例:

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

它的完成方法是完成一个已经打开的 (),放置转义的 (),然后打开另一个 ()。'\''

或者:

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

它是通过完成已经打开的一个 (),将引号放在另一个引号 () 中,然后打开另一个引号 () 来完成的。'"'"'

更多示例:在单引号字符串中转义单引号

评论

1赞 Igor Yagolnitser 6/18/2017
我尝试了 sh -c “echo '{”key“:”value“}'” 甚至 sh -c “echo '{'
4赞 divenex 10/19/2018
对于双引号来说,这似乎不必要地复杂:足以产生彼得的回答。echo "abc\"abc"abc"abc
4赞 prosoitos 5/3/2019
在这个简单的例子中,确实如此,但在嵌套引号的复杂情况下,可能有必要这样做,@kenorb的例子帮助我弄清楚了如何处理这些情况。
37赞 Beetle 8/18/2015 #4

Bash 允许你相邻放置字符串,它们最终会粘在一起。

所以这个:

echo "Hello"', world!'

生产

Hello, world!

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

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

生产

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 解释。像这样的引号将最终出现在结果变量中。" '

如果我对前面的例子进行相同的处理,它看起来像这样:

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

评论

0赞 Beetle 5/9/2022
我的第二个例子的一个微妙之处,我没有费心去解释,在这里我实际上给了 echo 三个单独的参数,因为字符串没有接触。但是该命令打印了所有三个,用空格分隔,因此它有点像您所期望的那样。不同的是,如果你输入它将输出,而如果你输入它将打印。echoechoecho a b ca b cecho 'a b c'a b c
12赞 Trisha Chatterjee 1/13/2017 #5

使用 $“string”。

在此示例中,它将是

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

注意(来自手册页):

前面带美元符号 ($“string”) 的双引号字符串将导致根据当前区域设置转换字符串。如果当前区域设置为 C 或 POSIX,则忽略美元符号。如果字符串被翻译和替换,则替换是双引号。

评论

3赞 David Kierans 4/12/2018
很好,不知道那个。
-10赞 Shilv 2/16/2017 #6

在双引号前添加以转义它,而不是"\"\

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

评论

10赞 tripleee 3/16/2017
反对票:你为什么要发布问题的答案?两者是完全截然不同且不相容的。cshbash
91赞 George Vasiliou 2/20/2017 #7

请记住,您可以使用需要回显的字符的 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"

# Output:
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.

评论

1赞 Yassine ElBadaoui 4/18/2017
+1,因为它解决了将 PS1 变量添加到 ~/.profile 的问题echo '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
2赞 Miguel Rojas Cortés 11/18/2019
这就是答案!我爱你,先生。
34赞 12oclocker 11/14/2017 #8

将双引号字符存储在变量中:

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

输出:

Double quotes "X" inside a double quoted string

评论

98赞 Andy Ray 2/14/2019
Bash 确实是最糟糕的语言
0赞 Artanis Zeratul 6/13/2019
@12oclocker,你的答案是万无一失的:D!特别是当使用“sed”命令时,它节省了我的一天!
1赞 Majal 2/6/2022 #9

要与 Bash 脚本中可能包含空格的变量一起使用,请在主引号内使用三引号,例如:

[ "$(date -r """$touchfile""" +%Y%m%d)" -eq "$(date +%Y%m%d)" ]

评论

2赞 Charles Duffy 9/8/2022
三重引号在 bash 中没有特殊含义:两个引号相互抵消,只留下第三个引号;使行为 100% 与仅使用一个引号相同。( 创建一个新的引用上下文,所以你一开始就不需要在其中转义双引号;只有反引号才有问题)。$( )
2赞 Charles Duffy 9/8/2022
自己试一试:工作方式与本答案中建议的代码完全相同。[ "$(date -r "$touchfile" +%Y%m%d)" -eq "$(date +%Y%m%d)" ]
0赞 Yisu Peng 4/23/2023 #10

使用怎么样.echo

例如

x=$(echo \"a b c\")

要使用该变量,

echo $x && ls "$x"

我更喜欢 echo 而不是 printf 的原因是它更直接。