ChatGPT解决这个技术问题 Extra ChatGPT

如何在双引号内转义双引号?

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

@kenorb 看起来不像那个问题的重复......
@Daenyth 这不是您希望最终用户有权访问的命令类型。批量加载脚本通常由受信任的用户(例如系统管理员或开发人员)服务器上运行。是的,如果最终用户控制 $dbtable 的值,则存在风险。不过,这非常并不常见,因为最终用户通常不会通过 SSH 连接到机器来加载他们的数据。

P
Peter

使用反斜杠:

echo "\""     # Prints one " character.

不工作。 x=ls; if [ -f "$(which "\""$x"\"")" ]; then echo exists; else echo broken; fi; 损坏,而 ... [ -f "$(which $x)" ]; ...... [ -f $(which "$x") ]; ... 工作正常。当 $x$(which "$x") 的结果给出任何带有空格或其他特殊字符的内容时,就会出现问题。一种解决方法是使用变量来保存 which 的结果,但是 bash 真的无法转义引号还是我做错了什么?
我正在尝试使用以下 grep -oh "\"\""$counter"\""\w*" 作为 bash 语法的一部分,其中 $counter 是一个变量。它不喜欢任何想法
你好,你的方法不行。请删除您的答案,因为它可能已经浪费了很多有用的时间。正确答案由@kenorb 发布,您的答案仅在终端调用时有效,但不适用于 bash 文件。在这里发布(可能是剪切粘贴解决方案)之前,您甚至自己尝试过吗:(?
P
Peter Mortensen

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

$ 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


我试过 sh -c "echo '{"key":"value"}'" 甚至 sh -c "echo '{''"''key''"'':''"''value''"' '}'" 试图将单词 key 和 value 括在双引号中,但在这两种情况下我都得到了 {key:value}
这对于双引号来说似乎是不必要的复杂:echo "abc\"abc" 足以产生 abc"abc 就像彼得回答中的那样。
确实在这个简单的例子中,但在嵌套引号的复杂情况下,可能有必要这样做,@kenorb 的例子帮助我弄清楚如何处理这些情况。
P
Peter Mortensen

请记住,您可以通过使用需要回显的字符的 ASCII 代码来避免转义。

例子:

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

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

我想如果我们尝试用反斜杠回显上面的字符串,我们将需要一个凌乱的两行反斜杠回显...... :)

对于变量赋值,这是等价的:

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 因为它解决了将 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 的问题
这就是答案!我爱你,先生。
P
Peter Mortensen

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


我没有费心解释的第二个 echo 示例的一个微妙之处在于,在这里我实际上给 echo 三个单独的参数,因为字符串没有接触。但是 echo 命令打印所有三个,用空格分隔,所以它有点像你期望的那样。不同之处在于,如果您输入 echo a b c,它将输出 a b c,而如果您输入 echo 'a b c',它将输出 a b c
P
Peter Mortensen

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

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

输出:

Double quotes "X" inside a double quoted string

Bash 确实是最糟糕的语言
@12oclocker,你的答案是万无一失的:D!特别是与“sed”命令一起使用时,它节省了我的时间!
P
Peter Mortensen

看看打印...

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

不使用 printf

echo -e $mystr

输出:说“嗨”

使用 printf

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

输出:说“嗨”


请注意,printf 也会转义更多字符,例如 '()
printf %q 生成为 eval 准备的字符串,而不是为 echo -e 格式化的字符串。
没有理由用 useless use of echo 包装 printf。您的两个示例都引用了错误。正确的解决方法是对变量进行双引号。
P
Peter Mortensen

使用 $"string"。

在这个例子中,它将是,

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

注意(来自 man page):

以美元符号 ($"string") 开头的双引号字符串将导致根据当前语言环境翻译该字符串。如果当前语言环境是 C 或 POSIX,则忽略美元符号。如果字符串被翻译和替换,则替换是双引号。


不错,不知道那个
M
Majal

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

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

P
Peter Mortensen

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

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

否决票:您为什么要发布对 bash 问题的 csh 答案?两者完全不同,互不相容。