以可移植的方式在 shell 脚本中对字符串进行 URL 编码

Eli*_*ley 2 linux shell posix urlencode

我需要使用将在 BusyBox Ash、Dash、Bash 和 ZSH 中运行的 shell 函数对字符串进行 URL 编码。

\n\n

它将在不同的 Docker 容器中运行,因此安装尽可能少的依赖项会更好。

\n\n

笔记:

\n\n
    \n
  • 问题“在 bash 脚本中对字符串进行 URL 编码”要求提供特定于 Bash 的脚本,唯一提供的答案取决于容器上安装的 PHP。

  • \n
  • 问题“如何为curl命令对数据进行urlencode? ”特定于curl,但肯定对非特定答案开放。然而,这 25 个答案似乎都不适用。那里的答案之一只能将数据发送到curl,而有些特定于bashksh,其他一些则需要Perl PHP Python Lua NodeJS Ruby gridsite -clientsuni2asciijqawksed安装。其中之一不需要额外的依赖项,但不保留a1和 等字符~

  • \n
\n\n

我期望得到什么:

\n\n
$> urlencode \'/\'\n%2f\n\n$> urlencode \'\xc3\xa7\'\n%c3%a7\n\n$> urlencode \'*\'\n%2a\n\n$> urlencode abc-123~6\nabc-123~6\n\n$> urlencode \'a test ?*\xc3\xa7 \'\na%20test%20%3f%2a%c3%a7%20\n
Run Code Online (Sandbox Code Playgroud)\n

Eli*_*ley 6

以下功能已在BusyBox AshDashBashZSH中进行了测试。

它们仅使用 shell 内置命令或核心命令,并且也应该在其他 shell 中工作。

urlencodepipe() {
  local LANG=C; local c; while IFS= read -r c; do
    case $c in [a-zA-Z0-9.~_-]) printf "$c"; continue ;; esac
    printf "$c" | od -An -tx1 | tr ' ' % | tr -d '\n'
  done <<EOF
$(fold -w1)
EOF
  echo
}

urlencode() { printf "$*" | urlencodepipe ;}
Run Code Online (Sandbox Code Playgroud)

怎么运行的:

  • 标准输入由 处理fold -w1,它重新格式化其输入,使其宽度为 1 列(换句话说,它\n在每个输入字符后添加一个 ,以便每个字符都在自己的行上)
  • 此处文档<<EOF将 的输出提供foldread命令
  • while命令一次接受一行(仅 1 个字符宽)read,该命令从 获取输入fold,并将其分配给变量c
  • case测试该字符是否需要进行 url 编码。如果没有,则打印它并继续 while 循环
  • od将每个输入字符转换为十六进制
  • tr将空格转换为%多行并连接多行

  • 很好,尽管它不是完全可移植的,因为“od”的输出与您在非 Linux 环境中的期望不同。对我来说, `urlencode ' '` 返回 `%%%%%%%%%%%20%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%`。用 `sed 's/ */%/g;s/%$//'` 替换第一个 `tr` 似乎有帮助,但它仍然无法将 `\n` 转换为 `%0d`。 (2认同)