比方说,你有一个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手册…
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"
由于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。
除了@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
希望在遇到类似问题时能有所帮助
以下是上面提到的唯一正确答案的详细说明:
有时我会在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"'
对一个人来说,这是一件可怕的事情——但你明白了吗