比方说,你有一个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
希望在遇到类似问题时能有所帮助
这两个版本都可以工作,或者通过使用转义单引号字符(\')进行连接,或者通过将单引号字符括在双引号("'")中进行连接。
问题的作者没有注意到,在他最后一次尝试转义时,多了一个单引号('):
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