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

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


当前回答

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

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

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

其他回答

我可以确认在单引号字符串中使用“\”作为单引号在Bash中是有效的,它可以用与线程前面的“粘合”参数相同的方式来解释。假设我们有一个带引号的字符串:' a '\ " B'\ " C'(这里所有的引号都是单引号)。如果传递给echo,则输出如下:A 'B' C。 在每个“\”中,第一个引号结束当前单引号字符串,后面的“\”将一个单引号粘到前一个字符串上(“\”是一种指定单引号而不开始一个单引号字符串的方法),最后一个引号打开另一个单引号字符串。

由于Bash 2.04语法$'string'允许一个转义限制集。

自Bash 4.4以来,$'string'还允许完整的c风格转义,使得$'string'的行为在以前的版本中略有不同。(以前可以使用$('string')形式。)

Bash 2.04及更新版本中的简单示例:

  $> echo $'aa\'bb'
  aa'bb

  $> alias myvar=$'aa\'bb'
  $> alias myvar
  alias myvar='aa'\''bb'

在你的情况下:

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

常见的转义序列按预期工作:

\'     single quote
\"     double quote
\\     backslash
\n     new line
\t     horizontal tab
\r     carriage return

下面是从man bash(4.4版)复制粘贴相关文档:

形式为$'string'的单词被特殊处理。单词扩展为字符串,反斜杠转义字符替换为ANSI C标准指定的字符。如果存在反斜杠转义序列,则按如下方式解码:

    \a     alert (bell)
    \b     backspace
    \e
    \E     an escape character
    \f     form feed
    \n     new line
    \r     carriage return
    \t     horizontal tab
    \v     vertical tab
    \\     backslash
    \'     single quote
    \"     double quote
    \?     question mark
    \nnn   the eight-bit character whose value is the octal 
           value nnn (one to three digits)
    \xHH   the eight-bit character whose value is the hexadecimal
           value HH (one or two hex digits)
    \uHHHH the Unicode (ISO/IEC 10646) character whose value is 
           the hexadecimal value HHHH (one to four hex digits)
    \UHHHHHHHH the Unicode (ISO/IEC 10646) character whose value 
               is the hexadecimal value HHHHHHHH (one to eight 
               hex digits)
    \cx    a control-x character

展开的结果是单引号,就好像美元符号不存在一样。


更多细节请参见bash.hackers.org wiki上的引用和转义:ANSI C like字符串。还要注意,“Bash Changes”文件(概述在这里)提到了很多与$'string'引用机制相关的更改和错误修复。

如何将一个特殊字符作为一个普通字符使用?它应该工作(与一些变化)在bash, zsh, mksh, ksh93和FreeBSD和busybox sh。

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

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

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

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

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

除了@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

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