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

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


当前回答

如果你已经安装了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)中引用该字符串。

其他回答

以下是上面提到的唯一正确答案的详细说明:

有时我会在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"'

对一个人来说,这是一件可怕的事情——但你明白了吗

我在他的博客上没有看到这个条目(请链接?),但根据gnu参考手册:

用单引号括住字符 (" ')保存的文字值 引号中的每个字符。一个 单引号之间不能出现 单引号,即使前面有 反斜杠。

所以bash不会理解:

别名x='y \'z '

但是,你可以用双引号括起来:

alias x="echo \'y "
> x
> 'y

这是另一个解决方案。这个函数将接受一个参数,并使用单引号字符适当地引用它,就像上面被投票的答案解释的那样:

single_quote() {
  local quoted="'"
  local i=0
  while [ $i -lt ${#1} ]; do
    local ch="${1:i:1}"
    if [[ "$ch" != "'" ]]; then
      quoted="$quoted$ch"
    else
      local single_quotes="'"
      local j=1
      while [ $j -lt ${#1} ] && [[ "${1:i+j:1}" == "'" ]]; do
        single_quotes="$single_quotes'"
        ((j++))
      done
      quoted="$quoted'\"$single_quotes\"'"
      ((i+=j-1))
    fi
    ((i++))
  done
  echo "$quoted'"
}

所以,你可以这样用:

single_quote "1 2 '3'"
'1 2 '"'"'3'"'"''

x="this text is quoted: 'hello'"
eval "echo $(single_quote "$x")"
this text is quoted: 'hello'

如何逃脱单引号(')和双引号(")与十六进制和八进制字符

如果使用像echo这样的东西,我有一些非常复杂,非常奇怪和难以逃避(想想:非常嵌套)的情况下,我唯一能做的就是使用八进制或十六进制代码!

下面是一些基本的例子来演示它是如何工作的:

1. 单引号示例,其中'转义为十六进制\x27或八进制\047(其对应的ASCII码):

十六进制\ x27 echo -e“让\x27s开始编码!” #或 echo -e“让\x27s开始编码!” 结果: 让我们开始编码吧! 八进制\ 047 echo -e“让047s开始编码!” #或 echo -e“让047s开始编码!” 结果: 让我们开始编码吧!

2. 双引号示例,其中"转义为十六进制\x22或八进制\042(其对应的ASCII码)。

注意:bash太疯狂了!有时甚至!Char有特殊的含义,必须从双引号内删除,然后转义为“像这样”\!或者完全用单引号括起来,像这样!,而不是在双引号内。

# 1. hex; also escape `!` by removing it from within the double quotes 
# and escaping it with `\!`
$ echo -e "She said, \x22Let\x27s get coding"\!"\x22"
She said, "Let's get coding!"

# OR put it all within single quotes:
$ echo -e 'She said, \x22Let\x27s get coding!\x22'
She said, "Let's get coding!"


# 2. octal; also escape `!` by removing it from within the double quotes 
$ echo -e "She said, \042Let\047s get coding"\!"\042"
She said, "Let's get coding!"

# OR put it all within single quotes:
$ echo -e 'She said, \042Let\047s get coding!\042'
She said, "Let's get coding!"


# 3. mixed hex and octal, just for fun
# also escape `!` by removing it from within the double quotes when it is followed by
# another escape sequence
$ echo -e "She said, \x22Let\047s get coding! It\x27s waaay past time to begin"\!"\042"
She said, "Let's get coding! It's waaay past time to begin!"

# OR put it all within single quotes:
$ echo -e 'She said, \x22Let\047s get coding! It\x27s waaay past time to begin!\042'
She said, "Let's get coding! It's waaay past time to begin!"

注意,如果你在需要的时候没有正确地转义!,就像我上面展示的两种方法一样,你会得到一些奇怪的错误,像这样:

$ echo -e "She said, \x22Let\047s get coding! It\x27s waaay past time to begin!\042"
bash: !\042: event not found

OR:

$ echo -e "She said, \x22Let\x27s get coding!\x22"
bash: !\x22: event not found

另一种选择:这允许在同一个bash字符串中混合展开和非展开

这里是另一个替代逃逸技术的演示。

首先,阅读@liori的主要回答,看看下面的第二种形式是如何工作的。现在,阅读这两种转义字符的方法。下面两个例子的输出是相同的:

CMD="gs_set_title"

# 1. 1st technique: escape the $ symbol with a backslash (\) so it doesn't 
# run and expand the command following it
echo "$CMD '\$(basename \"\$(pwd)\")'"

# 2. 2nd technique (does the same thing in a different way): escape the 
# $ symbol using single quotes around it, and the single quote (') symbol
# using double quotes around it
echo "$CMD ""'"'$(basename "$(pwd)")'"'"

样例输出:

Gs_set_title '$(basename "$(pwd)")' Gs_set_title '$(basename "$(pwd)")'

注意:对于我的gs_set_title bash函数,它在我的~/。Bash_aliases文件在这里,看到我的另一个答案。

引用:

https://en.wikipedia.org/wiki/ASCII#Printable_characters https://serverfault.com/questions/208265/what-is-bash-event-not-found/208266#208266 请参见我在这里的另一个回答:如何使用echo编写非ascii字符?

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

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

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

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

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