2017-06-13 14 views
0

我想对基于shell脚本的字符串进行编码。 我已经从网上下载了一个脚本。 它是:为什么在这个shell脚本中黑体不是URL编码?

#!/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 

根本没有输出。

你知道原因吗?

+0

谁在使用'url_encoder'的输出?像'curl'或'wget'这样的东西应该有必要的方式来编码它的输入。 – chepner

+0

url_encoder的输出应该按照要求先散列。 – AllenHu

回答

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字符 “'$ C”(< 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

是的,“读-r”的作品。感谢其他两个版本的url编码器。但它不是bash脚本,它是“#!/ bin/sh”,所以某些语法(例如for((i = 0; i <= {#str}; i + = 1));)可能不是支持的。 – AllenHu

+0

使用'read'会导致其他问题IFS必须取消设置以区分空格,制表符和换行符,例如'IFS = read -r';然而它会很慢'sh'显然不是好工具 –

+1

如果不能使用'bash'特定的问题这个问题不应该被标记'bash' –

1

Nahuel Fouilleul's helpful answer解释你的方法问题(-r从您的read命令丢失,造成\字符不需要解释。),并提供了更有效的解决方案bash

这里的一个更有效的,符合POSIX的溶液(sh兼容),其执行与单个awk命令的编码,假定输入字符串由32之间仅在ASCII/Unicode码点范围内的字符127,包含性地:

#!/bin/sh 

url_encoder() 
{                                                    
    awk -v url="$1" -v ORS= 'BEGIN { 
    # Create lookup table that maps characters to their code points. 
    for(n=32;n<=127;n++) ord[sprintf("%c",n)]=n 
    # Process characters one by one, either passing them through, if they 
    # need no encoding, or converting them to their %-prefixed hex equivalent. 
    for(i=1;i<=length(url);++i) { 
     char = substr(url, i, 1) 
     if (char !~ "[-_.~/a-zA-Z0-9]") char = sprintf("%%%x", ord[char]) 
     print char 
    } 
    printf "\n" 
    }' 
}