bash 如何在单引号字符串中转义单引号
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1250079/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to escape single quotes within single quoted strings
提问by cons
Let's say, you have a Bash alias
like:
比方说,你有一个alias
像这样的 Bash :
alias rxvt='urxvt'
which works fine.
这工作正常。
However:
然而:
alias rxvt='urxvt -fg '#111111' -bg '#111111''
won't work, and neither will:
不会工作,也不会:
alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''
So how do you end up matching up opening and closing quotes inside a string once you have escaped quotes?
那么,一旦您转义了引号,您如何最终匹配字符串中的开始和结束引号呢?
alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
seems ungainly although it would represent the same string if you're allowed to concatenate them like that.
看起来很笨拙,尽管如果允许您像这样连接它们,它将代表相同的字符串。
回答by liori
If you really want to use single quotes in the outermost layer, remember that you can glue both kinds of quotation. Example:
如果你真的想在最外层使用单引号,记住你可以粘合两种引号。例子:
alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
# ^^^^^ ^^^^^ ^^^^^ ^^^^
# 12345 12345 12345 1234
Explanation of how '"'"'
is interpreted as just '
:
解释如何'"'"'
解释为 just '
:
'
End first quotation which uses single quotes."
Start second quotation, using double-quotes.'
Quoted character."
End second quotation, using double-quotes.'
Start third quotation, using single quotes.
'
结束使用单引号的第一个引号。"
使用双引号开始第二个引用。'
引用字符。"
使用双引号结束第二个引用。'
开始第三个引用,使用单引号。
If you do not place any whitespaces between (1) and (2), or between (4) and (5), the shell will interpret that string as a one long word.
如果在 (1) 和 (2) 之间或 (4) 和 (5) 之间没有放置任何空格,shell 会将该字符串解释为一个长单词。
回答by Adrian Pronk
I always just replace each embedded single quote with the sequence: '\''
(that is: quote backslash quote quote) which closes the string, appends an escaped single quote and reopens the string.
我总是用序列替换每个嵌入的单引号:('\''
即:quote 反斜杠quotequote)关闭字符串,附加一个转义的单引号并重新打开字符串。
I often whip up a "quotify" function in my Perl scripts to do this for me. The steps would be:
我经常在我的 Perl 脚本中创建一个“引用”函数来为我做这件事。步骤是:
s/'/'\''/g # Handle each embedded quote
$_ = qq['$_']; # Surround result with single quotes.
This pretty much takes care of all cases.
这几乎可以处理所有情况。
Life gets more fun when you introduce eval
into your shell-scripts. You essentially have to re-quotify everything again!
当您引入eval
shell 脚本时,生活会变得更有趣。您基本上必须再次重新引用所有内容!
For example, create a Perl script called quotify containing the above statements:
例如,创建一个名为 quotify 的 Perl 脚本,其中包含上述语句:
#!/usr/bin/perl -pl
s/'/'\''/g;
$_ = qq['$_'];
then use it to generate a correctly-quoted string:
然后用它来生成一个正确引用的字符串:
$ quotify
urxvt -fg '#111111' -bg '#111111'
result:
结果:
'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
which can then be copy/pasted into the alias command:
然后可以将其复制/粘贴到别名命令中:
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
(If you need to insert the command into an eval, run the quotify again:
(如果您需要将命令插入到 eval 中,请再次运行 quotify:
$ quotify
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
result:
结果:
'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''
which can be copy/pasted into an eval:
可以复制/粘贴到评估中:
eval 'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''
回答by mj41
Since Bash 2.04syntax $'string'
(instead of just 'string'
; warning: do not confuse with $('string')
) is another quoting mechanism which allows ANSI C-like escape sequencesand do expansion to single-quoted version.
由于 Bash 2.04语法$'string'
(而不仅仅是'string'
; 警告:不要与 混淆$('string')
)是另一种引用机制,它允许类似 ANSI C 的转义序列并扩展到单引号版本。
Simple example:
简单的例子:
$> echo $'aa\'bb'
aa'bb
$> alias myvar=$'aa\'bb'
$> alias myvar
alias myvar='aa'\''bb'
In your case:
在你的情况下:
$> alias rxvt=$'urxvt -fg \'#111111\' -bg \'#111111\''
$> alias rxvt
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
Common escaping sequences works as expected:
常见的转义序列按预期工作:
\' single quote
\" double quote
\ backslash
\n new line
\t horizontal tab
\r carriage return
Below is copy+pasted related documentation from man bash
(version 4.4):
以下是从man bash
(4.4 版)复制+粘贴的相关文档:
Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard. Backslash escape sequences, if present, are decoded as follows:
$'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
The expanded result is single-quoted, as if the dollar sign had not been present.
扩展结果是单引号的,就好像美元符号不存在一样。
See Quotes and escaping: ANSI C like stringson bash-hackers.org wiki for more details. Also note that "Bash Changes"file (overview here) mentions a lot for changes and bug fixes related to the $'string'
quoting mechanism.
有关更多详细信息,请参阅bash-hackers.org wiki 上的Quotes and escaping: ANSI C like strings。另请注意,“Bash Changes”文件(此处的概述)提到了很多与$'string'
引用机制相关的更改和错误修复。
According to unix.stackexchange.com How to use a special character as a normal one?it should work (with some variations) in bash, zsh, mksh, ksh93 and FreeBSD and busybox sh.
根据unix.stackexchange.com如何使用特殊字符作为普通字符?它应该在 bash、zsh、mksh、ksh93 和 FreeBSD 以及 busybox sh 中工作(有一些变化)。
回答by Steve B.
I don't see the entry on his blog (link pls?) but according to the gnu reference manual:
我在他的博客上没有看到条目(请链接?),但根据gnu 参考手册:
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.
将字符括在单引号 (''') 中会保留引号内每个字符的字面值。单引号之间不能出现单引号,即使前面有反斜杠。
so bash won't understand:
所以bash不会理解:
alias x='y \'z '
alias x='y \'z '
however, you can do this if you surround with double quotes:
但是,如果你用双引号括起来,你可以这样做:
alias x="echo \'y "
> x
> 'y
回答by Mikhail at YugaByte
I can confirm that using '\''
for a single quote inside a single-quoted string does work in Bash, and it can be explained in the same way as the "gluing" argument from earlier in the thread. Suppose we have a quoted string: 'A '\''B'\'' C'
(all quotes here are single quotes). If it is passed to echo, it prints the following: A 'B' C
.
In each '\''
the first quote closes the current single-quoted string, the following \'
glues a single quote to the previous string (\'
is a way to specify a single quote without starting a quoted string), and the last quote opens another single-quoted string.
我可以确认'\''
在单引号字符串中使用单引号在 Bash 中确实有效,并且可以以与线程前面的“粘合”参数相同的方式进行解释。假设我们有一个带引号的字符串:('A '\''B'\'' C'
这里的所有引号都是单引号)。如果它被传递给回声,它打印的情况如下:A 'B' C
。在每一个中'\''
,第一个引号关闭当前的单引号字符串,下面的\'
将一个单引号粘在前一个字符串上(这\'
是一种指定单引号而不启动带引号的字符串的方法),最后一个引号打开另一个单引号字符串。
回答by Mikhail at YugaByte
Both versions are working, either with concatenation by using the escaped single quote character (\'), or with concatenation by enclosing the single quote character within double quotes ("'").
两个版本都可以使用,可以使用转义的单引号字符 (\') 进行连接,也可以通过将单引号字符括在双引号 ("'") 中进行连接。
The author of the question did not notice that there was an extra single quote (') at the end of his last escaping attempt:
问题的作者没有注意到在他最后一次转义尝试的末尾有一个额外的单引号('):
alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
│ │┊┊| │┊┊│ │┊┊│ │┊┊│
└─STRING──┘┊┊└─STRIN─┘┊┊└─STR─┘┊┊└─STRIN─┘┊┊│
┊┊ ┊┊ ┊┊ ┊┊│
┊┊ ┊┊ ┊┊ ┊┊│
└┴─────────┴┴───┰───┴┴─────────┴┘│
All escaped single quotes │
│
?
As you can see in the previous nice piece of ASCII/Unicode art, the last escaped single quote (\') is followed by an unnecessary single quote ('). Using a syntax-highlighter like the one present in Notepad++ can prove very helpful.
正如您在之前的 ASCII/Unicode 艺术作品中看到的那样,最后一个转义的单引号 (\') 后跟一个不必要的单引号 (')。使用 Notepad++ 中的语法高亮器可以证明非常有用。
The same is true for another example like the following one:
对于另一个示例也是如此,如下所示:
alias rc='sed '"'"':a;N;$!ba;s/\n/, /g'"'"
alias rc='sed '\'':a;N;$!ba;s/\n/, /g'\'
These two beautiful instances of aliases show in a very intricate and obfuscated way how a file can be lined down. That is, from a file with a lot of lines you get only one line with commas and spaces between the contents of the previous lines. In order to make sense of the previous comment, the following is an example:
这两个美丽的别名实例以一种非常复杂和模糊的方式显示了文件是如何排列的。也就是说,从包含很多行的文件中,您只能得到一行在前几行的内容之间带有逗号和空格。为了理解前面的评论,下面是一个例子:
$ cat Little_Commas.TXT
201737194
201802699
201835214
$ rc Little_Commas.TXT
201737194, 201802699, 201835214
回答by kenorb
Simple example of escaping quotes in shell:
在 shell 中转义引号的简单示例:
$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc
It's done by finishing already opened one ('
), placing escaped one (\'
), then opening another one ('
). This syntax works for all commands. It's very similar approach to the 1st answer.
它是通过完成已经打开的一个('
),放置逃脱的一个(\'
),然后打开另一个('
)来完成的。此语法适用于所有命令。这与第一个答案非常相似。
回答by nicerobot
I'm not specifically addressing the quoting issue because, well, sometimes, it's just reasonable to consider an alternative approach.
我不是专门解决引用问题,因为有时考虑替代方法是合理的。
rxvt() { urxvt -fg "#${1:-000000}" -bg "#${2:-FFFFFF}"; }
which you can then call as:
然后您可以将其称为:
rxvt 123456 654321
the idea being that you can now alias this without concern for quotes:
这个想法是你现在可以不用关心引号的别名:
alias rxvt='rxvt 123456 654321'
or, if you need to include the #
in all calls for some reason:
或者,如果您#
出于某种原因需要在所有调用中包含:
rxvt() { urxvt -fg "${1:-#000000}" -bg "${2:-#FFFFFF}"; }
which you can then call as:
然后您可以将其称为:
rxvt '#123456' '#654321'
then, of course, an alias is:
那么,当然,别名是:
alias rxvt="rxvt '#123456' '#654321'"
(oops, i guess i kind of did address the quoting :)
(哎呀,我想我确实解决了引用问题:)
回答by Nerrve
Since one cannot put single quotes within single quoted strings, the simplest and most readable option is to use a HEREDOC string
由于不能在单引号字符串中放置单引号,因此最简单且最易读的选项是使用 HEREDOC 字符串
command=$(cat <<'COMMAND'
urxvt -fg '#111111' -bg '#111111'
COMMAND
)
alias rxvt=$command
In the code above, the HEREDOC is sent to the cat
command and the output of that is assigned to a variable via the command substitution notation $(..)
在上面的代码中,HEREDOC 被发送到cat
命令,并通过命令替换符号将其输出分配给一个变量$(..)
Putting a single quote around the HEREDOC is needed since it is within a $()
需要在 HEREDOC 周围加上单引号,因为它在一个 $()
回答by Rob Jens
I just use shell codes.. e.g. \x27
or \\x22
as applicable. No hassle, ever really.
我只是使用 shell 代码......例如\x27
或\\x22
适用。没有麻烦,真的。