比方说,你有一个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 "#${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'"

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

其他回答

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

您试图将太多内容塞进太小的空间,因此使用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
-------------

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

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

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

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

$ echo "urxvt -fg '#111111' -bg '#111111'"
urxvt -fg '#111111' -bg '#111111'

这两个版本都可以工作,或者通过使用转义单引号字符(\')进行连接,或者通过将单引号字符括在双引号("'")中进行连接。

问题的作者没有注意到,在他最后一次尝试转义时,多了一个单引号('):

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
           │         │┊┊|       │┊┊│     │┊┊│       │┊┊│
           └─STRING──┘┊┊└─STRIN─┘┊┊└─STR─┘┊┊└─STRIN─┘┊┊│
                      ┊┊         ┊┊       ┊┊         ┊┊│
                      ┊┊         ┊┊       ┊┊         ┊┊│
                      └┴─────────┴┴───┰───┴┴─────────┴┘│
                          All escaped single quotes    │
                                                       │
                                                       ?

正如您在前面漂亮的ASCII/Unicode艺术中看到的,最后一个转义单引号(\')后面跟着一个不必要的单引号(')。使用notepad++中提供的语法高亮显示工具非常有用。

另一个例子也是如此,比如下面这个:

alias rc='sed '"'"':a;N;$!ba;s/\n/, /g'"'"
alias rc='sed '\'':a;N;$!ba;s/\n/, /g'\'

这两个漂亮的别名实例以一种非常复杂和模糊的方式显示了如何排列文件。也就是说,从一个有很多行的文件中,您只能得到一行,前几行内容之间有逗号和空格。为了理解前面的评论,下面是一个例子:

$ cat Little_Commas.TXT
201737194
201802699
201835214

$ rc Little_Commas.TXT
201737194, 201802699, 201835214

如果你在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!'
shell_escape () {
    printf '%s' "'${1//\'/\'\\\'\'}'"
}

实现说明:

双引号,这样我们可以很容易地输出换行单引号,并使用${…}语法 Bash的搜索和替换如下:${varname//search/replacement} 我们用“\”代替“\” '\ "编码单个',如下所示: 单引号结束 \'编码a '(需要反斜杠,因为我们不在引号内) 又开始了单引号 Bash自动连接字符串,中间没有空格 在每个\和`之前都有一个\,因为这是${…//…/…的转义规则。}。

string="That's "'#@$*&^`(@#'
echo "original: $string"
echo "encoded:  $(shell_escape "$string")"
echo "expanded: $(bash -c "echo $(shell_escape "$string")")"

注:始终编码为单引号字符串,因为它们比双引号字符串简单得多。