带引号的 Bash 参数扩展 $parameter/pattern/string
Posted
技术标签:
【中文标题】带引号的 Bash 参数扩展 $parameter/pattern/string【英文标题】:Bash parameter expansion $parameter/pattern/string with quotes带引号的 Bash 参数扩展 $parameter/pattern/string 【发布时间】:2015-01-16 04:05:26 【问题描述】:这是我在 SO 上的第一篇文章(虽然潜伏了很长时间),所以我提前为我肯定要犯的众多“失礼”和其他错误道歉。
我已经在谷歌上找了一段时间了,现在试图找到在双引号内的参数扩展内如何解析引号的答案,似乎我要么有错误的关键字,要么是一个非常扭曲的尝试尝试这个。
例如,如果我有一个像It's a complicated string
这样的字符串,我想使用bash 的参数扩展$parameter/pattern/string
将该字符串转换为序列It'\''s a complicated string
。 我知道我可以使用许多其他内置或外部工具之一来实现该结果(我自己非常喜欢 sed),但这个问题实际上是关于了解 bash 的想法,以便我可以把我的自己的心来放松。
Bash's reference 在描述其“模式”时似乎没有具体说明在这种特殊情况下会发生什么,而the closest question on SO 在我的情况下似乎不起作用:
$ echo "$str"
It's a complicated string
$ echo "$str//'/'\''"
> ^C
$ echo "$str//'/'\''"
> ^C
$ echo "$str//\'/'\''"
> ^C
$ echo "$str//\'/\'\''"
> ^C
$ echo "$str//\'/\'\'\'"
It\'\'\'s a complicated string
$ echo "$str//\\'/\'\'\'"
It's a complicated string
$ echo "$str//\\'/\\'\'\'"
It's a complicated string
$ echo "$str//\\'/\\'\\'\'"
It's a complicated string
$ echo "$str//\\'/\\'\\'\\'"
It's a complicated string
$ echo "$str//\\\'/\\'\\'\\'"
> ^C
$ echo "$str//\\\'/\\\'\\'\\'"
It's a complicated string
$ echo "$str//\\\'/\\\'\\\'\\'"
> ^C
$ echo "$str//\\\'/\\\'\\\'\\\'"
It's a complicated string
(> ^C
行表示引号未正确解析,系统提示我输入更多内容,我每次使用 Ctrl-C 时都无情地拒绝。)
请大家解释一下 bash 究竟是如何看待这个问题的?我真的希望这只是我们之间的沟通问题,我有点喜欢他。 :)
编辑:
对于那些想知道的人,Etan Reisner 的回答很有效:
$ q=\'
$ echo "$str//\'/$q\'$q"
It'\''s a complicated string
至于斯普特尼克的回答,我更疑惑了:
$ echo "$str//\047/\047\\\047\047"
It's a complicated string
$ echo "$str//\047/\047\047"
It's a complicated string
$ echo "$str//\'/\047\'\047"
It\047\'\047s a complicated string
$ echo "$str//\'/\047\047\047"
It\047\047\047s a complicated string
$ echo "$str//'/\047\047\047"
> ^C
$ echo "$str//\047/\047\047\047"
It's a complicated string
$ echo "$str//\047/\047\\\047\047"
It's a complicated string
EDIT2:
显然,这是一个至少影响 bash 4.1 和 4.2 的错误,并已在 bash 4.3 中修复。因此,从上面的测试中没有什么可以理解的。
【问题讨论】:
使用\\'
,对于 bash,你有一个反斜杠并且你正在打开一个单引号(而 Bash 正在等待你关闭它——你可以通过按 Ctrl-C 来取消它)。尝试一些有趣的事情:不要按 Ctrl-C,而是输入 I love bananas'"
并享受。
@gniourf_gniourf 我可以理解$parameter/pattern/string
的“模式”部分中的行为,但在“字符串”部分中,所有字符都应该是文字吗?
一个更好的问题是,为什么要创建这样的字符串?原件是一个包含单引号的完全有效的字符串;您的编辑似乎试图在字符串中添加带引号的单引号(我可能会添加不正确),以尝试在字符串中包含 bash
语法。
@EtanReisner 来自手册:模式被扩展以产生一个模式,就像在文件名扩展中一样。所以这里没有惊喜。
【参考方案1】:
以下作品(带或不带双引号):
echo "$str//\'/\'\\\'\'"
每个单引号都用反斜杠转义,以防止它开始单引号字符串。文字反斜杠也在替换模式中被转义。
从bash
4.3 会话直接复制和粘贴:
$ str="It's a complicated string"
$ echo "$str//\'/\'\\\'\'"
It'\''s a complicated string
$ echo $str//\'/\'\\\'\'
It'\''s a complicated string
bash
3.2 中的输出是相同的。
【讨论】:
带有不会生成所需输出的引号。如果没有引号,它会这样做,但这可能不再安全了。 Etan 是对的:当我运行它时,我得到了It\'\\'\'s a complicated string
真的吗?我得到了我认为在 3.2 和 4.3 中想要的输出。
@chepner Strange...我在 bash 4.2 上,无论是否使用 posix 模式,我都会得到错误的输出。回家后我会尝试更新的 bash 版本。也许我刚刚发现了一个只影响 4.2 的“功能”?
4.1 显示的输出与您在上面显示的相同。这可能是 4.0(或 4.1?)中引入的错误,已在 4.3 中修复。【参考方案2】:
我无法解释 bash 到底在做什么,但与 @sputnick 类似,我的建议是不要玩游戏。
q=\'
echo "$str//\'/$q\'$q"
【讨论】:
这确实有效(我编辑了我的问题以反映这一点),但在解析我的初始命令行时我仍然不理解 bash 的奇怪行为。【参考方案3】:与其尝试奇怪的转义游戏,不如尝试使用ascii
表示单引号:\047
见
man 7 ascii
【讨论】:
我的 bash 似乎看不出` and the escape sequence
\047` 之间有任何区别(请参阅我编辑的答案)。以上是关于带引号的 Bash 参数扩展 $parameter/pattern/string的主要内容,如果未能解决你的问题,请参考以下文章