比方说,你有一个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'\''

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


当前回答

在给定的例子中,简单地使用双引号而不是单引号作为外部转义机制:

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

这种方法适用于您只想将固定字符串传递给命令的许多情况:只需检查shell如何通过echo解释双引号字符串,并在必要时使用反斜杠转义字符。

在这个例子中,你会看到双引号足以保护字符串:

$ echo "urxvt -fg '#111111' -bg '#111111'"
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的答案是一样的,但我觉得这解释得更好。而且他的回答在结尾有两个多余的单引号。)

这个函数:

quote () 
{ 
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

允许引用“内部”。像这样使用:

$ quote "urxvt -fg '#111111' -bg '#111111'"
'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

如果要引用的行变得更复杂,比如双引号和单引号混合在一起,那么在变量中获得要引用的字符串可能会变得相当棘手。当出现这种情况时,在脚本中编写需要引用的确切行(类似于此)。

#!/bin/bash

quote ()
{
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

while read line; do
    quote "$line"
done <<-\_lines_to_quote_
urxvt -fg '#111111' -bg '#111111'
Louis Theroux's LA Stories
'single quote phrase' "double quote phrase"
_lines_to_quote_

将输出:

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
'Louis Theroux'\''s LA Stories'
''\''single quote phrase'\'' "double quote phrase"'

所有在单引号内正确引用的字符串。

我在他的博客上没有看到这个条目(请链接?),但根据gnu参考手册:

用单引号括住字符 (" ')保存的文字值 引号中的每个字符。一个 单引号之间不能出现 单引号,即使前面有 反斜杠。

所以bash不会理解:

别名x='y \'z '

但是,你可以用双引号括起来:

alias x="echo \'y "
> x
> 'y

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

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

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

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

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

以下是上面提到的唯一正确答案的详细说明:

有时我会在ssh上使用rsync下载,并且必须转义一个带有'两次!(天啊!)一次用于bash,一次用于ssh。这里也使用了相同的交替引用分隔符原则。

例如,假设我们想要:Louis Theroux的LA Stories……

首先,将Louis Theroux用单引号括起来表示bash,用双引号括起来表示ssh: “路易泰鲁”的 然后使用单引号转义双引号" " 使用双引号来转义撇号"'" 然后重复#2,使用单引号转义双引号“” 然后将LA Stories包含在bash的单引号中,ssh的双引号中:' ' LA Stories ' '

看哪!你会得到这样的结果:

rsync -ave ssh '"Louis Theroux"''"'"'"'"''"s LA Stories"'

对一个人来说,这是一件可怕的事情——但你明白了吗