比方说,你有一个Bash别名:

alias rxvt='urxvt'

这很好。

然而:

alias rxvt='urxvt -fg '#111111' -bg '#111111''

不管用,也不管用:

alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''

那么,一旦有转义引号,如何在字符串中匹配开始和结束引号呢?

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''

看起来很笨拙,但如果允许像这样连接它们,它将表示相同的字符串。


当前回答

显然,简单地用双引号括起来会更容易,但这其中的挑战在哪里呢?下面是只用单引号的答案。我用的是变量而不是别名这样更容易打印出来证明,但这和使用别名是一样的。

$ rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'
$ echo $rxvt
urxvt -fg '#111111' -bg '#111111'

解释

关键在于,您可以关闭单引号,并根据需要多次重新打开它。例如,foo='a " b'与foo='ab'相同。所以你可以关闭单引号,放入一个文字单引号\',然后重新打开下一个单引号。

分解图

这个图通过使用括号来显示单引号的开始和结束位置,使之更加清晰。引号不像圆括号那样“嵌套”。你也可以注意颜色的高亮,这是正确的应用。引号中的字符串是栗色的,而\'是黑色的。

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'    # original
[^^^^^^^^^^] ^[^^^^^^^] ^[^^^^^] ^[^^^^^^^] ^    # show open/close quotes
 urxvt -fg   ' #111111  '  -bg   ' #111111  '    # literal characters remaining

(这基本上和Adrian的答案是一样的,但我觉得这解释得更好。而且他的回答在结尾有两个多余的单引号。)

其他回答

恕我直言,真正的答案是你不能在单引号字符串中转义单引号。

它是不可能的。

如果我们假设使用bash。

从bash手册…

Enclosing characters in single quotes preserves the literal value of each
character within the quotes.  A single quote may not occur
between single quotes, even when preceded by a backslash.

您需要使用其他字符串转义机制之一"或\

没有什么神奇的关于别名要求它使用单引号。

以下两种方法都可以在bash中工作。

alias rxvt="urxvt -fg '#111111' -bg '#111111'"
alias rxvt=urxvt\ -fg\ \'#111111\'\ -bg\ \'#111111\'

后者使用\来转义空格字符。

#111111要求单引号也没有什么神奇之处。

下面的选项实现了与其他两个选项相同的结果,因为rxvt别名按预期工作。

alias rxvt='urxvt -fg "#111111" -bg "#111111"'
alias rxvt="urxvt -fg \"#111111\" -bg \"#111111\""

您还可以直接逃避麻烦的#

alias rxvt="urxvt -fg \#111111 -bg \#111111"

如果你真的想在最外层使用单引号,记住你可以把这两种引号粘在一起。例子:

 alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
 #                     ^^^^^       ^^^^^     ^^^^^       ^^^^
 #                     12345       12345     12345       1234

解释“”“”如何被解释为正义:

'结束第一个使用单引号的引号。 开始第二次引用,使用双引号。 引用字符。 结束第二次引用,使用双引号。 开始第三个引号,使用单引号。

如果在(1)和(2)之间或(4)和(5)之间没有放置任何空白,shell将把该字符串解释为一个长单词。

除了@JasonWoof的完美答案,我想展示我是如何解决相关问题的

在我的例子中,用“\”编码单引号并不总是足够的,例如,如果字符串必须用单引号引用,但是引号的总数导致奇数

#!/bin/bash

# no closing quote
string='alecxs\'solution'

# this works for string
string="alecxs'solution"
string=alecxs\'solution
string='alecxs'\''solution'

让我们假设字符串是一个文件名,我们需要在一个列表中保存引用的文件名(如stat -c%N ./* > list)

echo "'$string'" > "$string"
cat "$string"

但是处理这个列表将失败(取决于字符串总共包含多少引号)

while read file
  do
    ls -l "$file"
    eval ls -l "$file"
done < "$string"

解决方法:用字符串操作编码引号

string="${string//$'\047'/\'\$\'\\\\047\'\'}"

# result
echo "$string"

现在它起作用了,因为报价总是平衡的

echo "'$string'" > list
while read file
  do
    ls -l "$file"
    eval ls -l "$file"
done < list

希望在遇到类似问题时能有所帮助

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

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

它是通过结束已经打开的一个('),放置转义的一个(\'),然后打开另一个(')来完成的。此语法适用于所有命令。这和第一个答案非常相似。

需要一个最小的答案,这样人们就可以开始了,而不需要花很多时间,因为我不得不筛选那些雄辩的人。

没有办法转义单引号或单引号内的任何内容。

下面是一个完整的命令,也许令人惊讶:

$ echo '\'

其输出为:

\

甚至对于bash的长期用户来说,反斜杠在单引号内也没有任何意义。其他事情也一样。