比方说,你有一个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'\''
看起来很笨拙,但如果允许像这样连接它们,它将表示相同的字符串。
下面是我的观点——如果一个人想要sh可移植,而不仅仅是特定于bash(解决方案不是很有效,但是,因为它启动了一个外部程序——sed):
把它放在你的PATH中的quote.sh(或者只是引用)中:
# this works with standard input (stdin)
quote() {
echo -n "'" ;
sed 's/\(['"'"']['"'"']*\)/'"'"'"\1"'"'"'/g' ;
echo -n "'"
}
case "$1" in
-) quote ;;
*) echo "usage: cat ... | quote - # single-quotes input for Bourne shell" 2>&1 ;;
esac
一个例子:
$ echo -n "G'day, mate!" | ./quote.sh -
'G'"'"'day, mate!'
当然,它会转换回:
$ echo 'G'"'"'day, mate!'
G'day, mate!
解释:基本上我们必须用引号包围输入',然后也用这个微型怪物替换任何单引号:' ' ' ' '(以配对结束开头引号',通过双引号包装它来转义找到的单引号- "'",然后最后发出一个新的开头单引号',或者在伪符号中:' + "' ' + ' == ' ' ' ' ')
一种标准的方法是使用sed和下面的替换命令:
s/\(['][']*\)/'"\1"'/g
但是,有一个小问题是,为了在shell中使用它,需要在sed表达式本身中转义所有这些单引号字符——这会导致类似的结果
sed 's/\(['"'"']['"'"']*\)/'"'"'"\1"'"'"'/g'
(构建此结果的一个好方法是将原始表达式s/\(['][']*\)/'"\1"'/g提供给Kyle Rose'或George V. Reilly的脚本)。
最后,期望输入来自stdin是有意义的——因为通过命令行参数传递它可能已经太麻烦了。
(哦,也许我们想要添加一个小的帮助消息,这样当有人以。/quote.sh运行脚本时,脚本不会挂起——help想知道它是做什么的。)
由于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。
如果你已经安装了GNU Parallel,你可以使用它的内部引用:
$ parallel --shellquote
L's 12" record
<Ctrl-D>
'L'"'"'s 12" record'
$ echo 'L'"'"'s 12" record'
L's 12" record
从版本20190222,你甚至可以——shellquote多次:
$ parallel --shellquote --shellquote --shellquote
L's 12" record
<Ctrl-D>
'"'"'"'"'"'"'L'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'s 12" record'"'"'"'"'"'"'
$ eval eval echo '"'"'"'"'"'"'L'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'s 12" record'"'"'"'"'"'"'
L's 12" record
它将在所有受支持的shell(不仅仅是bash)中引用该字符串。