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

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


当前回答

另一种解决太多嵌套引用层问题的方法:

您试图将太多内容塞进太小的空间,因此使用bash函数。

问题是您试图有太多的嵌套级别,而基本的别名技术还不够强大。使用这样的bash函数,使单引号、双引号、反引号和传入的参数都像我们预期的那样正常处理:

lets_do_some_stuff() {
    tmp=$1                       #keep a passed in parameter.
    run_your_program $@          #use all your passed parameters.
    echo -e '\n-------------'    #use your single quotes.
    echo `date`                  #use your back ticks.
    echo -e "\n-------------"    #use your double quotes.
}
alias foobarbaz=lets_do_some_stuff

然后,您可以使用$1和$2变量以及单引号、双引号和反引号,而不用担心别名函数破坏它们的完整性。

这个程序输出:

el@defiant ~/code $ foobarbaz alien Dyson ring detected @grid 10385
alien Dyson ring detected @grid 10385
-------------
Mon Oct 26 20:30:14 EDT 2015
-------------

其他回答

我总是将每个嵌入的单引号替换为序列:'\ "(即:quote反斜杠quote quote),它关闭字符串,附加一个转义的单引号并重新打开字符串。


我经常在Perl脚本中创建一个“quotify”函数来为我做这件事。步骤如下:

s/'/'\\''/g    # Handle each embedded quote
$_ = qq['$_']; # Surround result with single quotes.

这基本上解决了所有情况。

当您在shell脚本中引入eval时,生活会变得更加有趣。你必须重新对所有东西进行报价!

例如,创建一个名为quotify的Perl脚本,包含上面的语句:

#!/usr/bin/perl -pl
s/'/'\\''/g;
$_ = qq['$_'];

然后使用它生成一个正确引用的字符串:

$ quotify
urxvt -fg '#111111' -bg '#111111'

结果:

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

然后可以复制/粘贴到alias命令:

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

(如果需要在eval中插入该命令,请再次运行quotify:

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

结果:

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

可以复制/粘贴到eval中:

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

我并没有特别提到引用问题,因为,有时候,考虑另一种方法是合理的。

rxvt() { urxvt -fg "#${1:-000000}" -bg "#${2:-FFFFFF}"; }

你可以调用它为:

rxvt 123456 654321

这个想法是你现在可以在不考虑引号的情况下使用别名:

alias rxvt='rxvt 123456 654321'

或者,如果你出于某种原因需要在所有调用中包含#:

rxvt() { urxvt -fg "${1:-#000000}" -bg "${2:-#FFFFFF}"; }

你可以调用它为:

rxvt '#123456' '#654321'

那么,当然,别名是:

alias rxvt="rxvt '#123456' '#654321'"

(哦,我想我确实提到了引用:)

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

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

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

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

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

如果你在Python 2或Python 3中生成shell字符串,下面的语句可能有助于引用参数:

#!/usr/bin/env python

from __future__ import print_function

try:  # py3
    from shlex import quote as shlex_quote
except ImportError:  # py2
    from pipes import quote as shlex_quote

s = """foo ain't "bad" so there!"""

print(s)
print(" ".join([shlex_quote(t) for t in s.split()]))

这将输出:

foo ain't "bad" so there!
foo 'ain'"'"'t' '"bad"' so 'there!'

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

它是不可能的。

如果我们假设使用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"