我遇到了一些意想不到的行为bash
。这是我的输入/输出:
nepumuk@pc:~$ type URL
URL is a function
URL ()
{
echo -e "${_//%/\\x}"
}
nepumuk@pc:~$ URL %2f
URL
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2F
/
nepumuk@pc:~$ type URL
URL is a function
URL ()
{
echo -e "${_//%/\\x}"
}
nepumuk@pc:~$ URL %2f
URL
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2f
/
bash函数文件中对应的部分是:
url() {
: "${*//+/ }"
echo -e "${_//%/\\x}"
}
export -f url
URL() {
echo -e "${_//%/\\x}"
}
export -f URL
在测试期间,我更改了的内容URL
以echo -e "${@//%/\\x}"
查看是否有变化。打开一个新的终端(模拟器?)窗口并使用后者,我得到了
nepumuk@pc:~$ URL %2f
/usr/share/bash-completion/bash_completion
nepumuk@pc:~$ URL %2f
/
nepumuk@pc:~$ URL %2f
/
虽然我可以完全重现(并使用前者,因为它给出了所需的输出),但我很高兴有一个解释。
答案1
在bash
变量中$_
扩展为先前运行命令的最后一个参数(除其他事项外)。
url() { : "${*//+/ }" echo -e "${_//%/\\x}" }
具有某种意义,因为 的扩展${*//+/ }
首先作为任意一个参数传递给:
无操作命令。
这是为了将+
位置参数中的 s 替换为空格,并将结果字符串与中间的第一个字符连接起来(引用时$IFS
的通常效果)。$*
然后第二个命令获取结果字符串,用其中的%
s替换\x
并将结果传递给echo
.
在 中bash
,当posix
和xpg_echo
选项未同时启用时,其echo
内置支持-e
可用于扩展一些转义序列的选项,其中一些\xHH
扩展为具有与 0xHH 十六进制数相对应的值的字节。因此它将替换%HH
为相应的字节值,从而实际上进行 URI %XX 解码。
如果删除第一个:
命令,则$_
第二个命令中将包含调用该函数之前传递给命令运行的最后一个参数。
在这里,编写该函数的人似乎都使用了这个$_
技巧来避免使用临时变量。然而,这使得代码变得不必要的复杂并且难以阅读和理解。
uri_decode() {
local IFS=' ' # make sure arguments are joined with spaces rather than
# make some assumption on what $IFS may currently contain
local tmp="$*" # positional parameters joined with spaces
tmp=${tmp//+/ } # replace +s with spaces
tmp=${tmp//[%]/\\x} # replace % with \\x. Using [%] instead of % for
# increased portability.
printf '%b\n' "$tmp" # pass the result to printf for expanding of the \x
# sequences, avoiding echo whose behaviour depends on
# the environment, and would give incorrect results
# for strings like -Enee
}
如果您想要一个不执行 + -> 空格转换的变体,只需删除该tmp=${tmp//+/ }
部分即可。