为什么blackslash不是在这个shell脚本中编码的url?

时间:2017-06-13 09:17:06

标签: shell awk urlencode

我正在尝试将url编码为基于shell脚本的字符串。 我从互联网上下载了一个脚本。 它是:

#!/bin/sh
url_encoder() 
{                                                                                                                                                                                                              

echo -n "$1" | awk -v ORS="" '{ gsub(/./,"&\n") ; print }' | while read l;
do                                                                                                                                                                                                                            

case "$l" in                                                                                                                                                                                                                
  [-_.~/a-zA-Z0-9] ) echo -n ${l} ;;                                                                                                                                                                                      
      "" ) echo -n %20 ;;                                                                                                                                                                                                 
       * ) printf '%%%02X' "'$l"                                                                                                                                                                                          
esac                                                                                                                                                                                                                        

done              
}

echo ""

} 

上述代码的基本思想是 (1)将输入字符串转换为行,每行有一个字符 (2)对于每一行,url编码字符

所以如果我跑

$url_encoder "abc:"

输出将是" abc%3A",这是正确的

但如果我跑

$url_encoder "\\"      # I want to encode the backslash, so I use 2 "\" here

根本没有输出。

你知道原因吗?

2 个答案:

答案 0 :(得分:4)

无需使用读取哪个慢,变量扩展可以做一个子串,不需要特别处理空格字符,它可以作为默认处理

url_encoder() {
    local i str=$1 c
    for ((i=0;i<${#str};i+=1)); do
        c=${str:i:1}
        case "$c" in
            [-_.~/a-zA-Z0-9] ) echo -n "${c}" ;;
            * ) printf '%%%02X' "'$c" ;;
        esac
    done
}
 l='\'
 printf '%%%02X' "'$l"

反斜杠消失的原因是因为read具有特殊含义,-r选项应该用来避免。

https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html#index-read

注意~也应编码为http://www.rfc-editor.org/rfc/rfc1738.txt

printf参数以引号(单引号或双引号)开头,仅处理ascii字符&#34;&#39; $ c&#34; (小于128)。

url_encoder() { (
    LC_ALL=C
    str=$1
    for ((i=0;i<${#str};i+=1)); do
        c=${str:i:1}
        if [[ $c = [-_./a-zA-Z0-9] ]]; then
            echo -n "${c}"
        elif [[ $c = [$'\1'-$'\x7f'] ]]; then
            printf '%%%02X' "'$c"
        else
            printf '%%%s' $(echo -n "$c" | od  -An -tx1)
        fi
    done
)}

答案 1 :(得分:1)

Nahuel Fouilleul's helpful answer解释了您的方法存在的问题(-r命令中遗漏了read,导致对\字符的不必要解释。)并提供了更高效的{{} {1}}解决方案。

这里是一个更高效,符合POSIX标准的解决方案(bash - 兼容),它使用单个sh命令执行编码,假设输入字符串仅由字符组成ASCII / Unicode代码点范围介于32和127之间,包括:

awk