相同输入的不同 bash 输出

相同输入的不同 bash 输出

我遇到了一些意想不到的行为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

在测试期间,我更改了的内容URLecho -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,当posixxpg_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//+/ }部分即可。

相关内容