用波形符替换子串时行为不一致"〜"在BASH参数展开

时间:2018-01-03 23:32:36

标签: linux bash shell sh bash4

在尝试编写快速函数时,我在几个不同服务器的BASH参数扩展中遇到了一些奇怪的不一致行为。

在BASH的某些版本中,要在子字符串替换中使用代字号,必须转义代字号,否则它将重新展开到主目录:

foo=~/data # ~ is expanded to $HOME
bar1="${foo/#$HOME/\~}" # returns ~/data
bar2="${foo/#$HOME/"~"}" # returns ~/data
bar3="${foo/#$HOME/~}" # returns /home/user/data

在其他系统上,它不会被重新展开,并且尝试转义波形符将把字面转义字符添加到字符串中:

foo=~/data # ~ is expanded to $HOME
bar1="${foo/#$HOME/\~}" # returns \~/data
bar2="${foo/#$HOME/"~"}" # returns "~"/data
bar3="${foo/#$HOME/~}" # returns ~/data

注意我的目标是插入文字字符串"〜"。

无需逃避的BASH版本在这里:

GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin16.3.0)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

GNU bash, version 4.2.37(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

需要转义的BASH版本在这里:

GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

那是怎么回事?

2 个答案:

答案 0 :(得分:0)

eval是另一种选择。

eval bar1="${foo/#$HOME/\~}"
eval bar2="${foo/#$HOME/"~"}"
eval bar3="${foo/#$HOME/~}"

现在你得到/home/foo/data所有三种情况。

答案 1 :(得分:0)

@iBug发布了如何确保我们始终扩展代字号。为确保我们始终在任何系统上获得波形符,请使用:

bar="${foo/#$HOME/~}" # returns ~/data or /home/user/data
[[ "$bar" =~ "$HOME"* ]] && bar="${foo/#$HOME/\~}"

仅当原始的非转义波浪号被展开时,才使用转义波浪号重做替换。