Как урленкодировать данные для команды curl? - PullRequest
274 голосов
/ 17 ноября 2008

Я пытаюсь написать bash-скрипт для тестирования, который принимает параметр и отправляет его через curl на веб-сайт. Мне нужно URL кодировать значение, чтобы убедиться, что специальные символы обрабатываются правильно. Каков наилучший способ сделать это?

Вот мой основной сценарий:

#!/bin/bash
host=${1:?'bad host'}
value=$2
shift
shift
curl -v -d "param=${value}" http://${host}/somepath $@

Ответы [ 30 ]

5 голосов
/ 07 июля 2014

Вот версия узла:

uriencode() {
  node -p "encodeURIComponent('${1//\'/\\\'}')"
}
4 голосов
/ 18 декабря 2013

Другой подход php:

echo "encode me" | php -r "echo urlencode(file_get_contents('php://stdin'));"
3 голосов
/ 31 января 2017

Вот моя версия для busybox ash shell для встроенной системы, я изначально принял вариант Орвеллофил:

urlencode()
{
    local S="${1}"
    local encoded=""
    local ch
    local o
    for i in $(seq 0 $((${#S} - 1)) )
    do
        ch=${S:$i:1}
        case "${ch}" in
            [-_.~a-zA-Z0-9]) 
                o="${ch}"
                ;;
            *) 
                o=$(printf '%%%02x' "'$ch")                
                ;;
        esac
        encoded="${encoded}${o}"
    done
    echo ${encoded}
}

urldecode() 
{
    # urldecode <string>
    local url_encoded="${1//+/ }"
    printf '%b' "${url_encoded//%/\\x}"
}
3 голосов
/ 20 июня 2012

Рубин, для полноты

value="$(ruby -r cgi -e 'puts CGI.escape(ARGV[0])' "$2")"
2 голосов
/ 29 апреля 2011

Вот преобразование в одну строку с использованием Lua, похожее на ответ blueyed за исключением того, что все незарезервированные символы RFC 3986 оставлены незакодированными (как этот ответ ):

url=$(echo 'print((arg[1]:gsub("([^%w%-%.%_%~])",function(c)return("%%%02X"):format(c:byte())end)))' | lua - "$1")

Кроме того, вам может потребоваться убедиться, что переводы строки в вашей строке преобразованы из LF в CRLF, и в этом случае вы можете вставить gsub("\r?\n", "\r\n") в цепочку перед кодированием процента.

Вот вариант, который в нестандартном стиле application / x-www-form-urlencoded выполняет эту нормализацию новой строки, а также кодирует пробелы как '+' вместо '% 20 '(который, вероятно, может быть добавлен к фрагменту Perl с использованием аналогичной техники).

url=$(echo 'print((arg[1]:gsub("\r?\n", "\r\n"):gsub("([^%w%-%.%_%~ ]))",function(c)return("%%%02X"):format(c:byte())end):gsub(" ","+"))' | lua - "$1")
2 голосов
/ 31 декабря 2016

Вот функция POSIX, чтобы сделать это:

encodeURIComponent() {
  awk 'BEGIN {while (y++ < 125) z[sprintf("%c", y)] = y
  while (y = substr(ARGV[1], ++j, 1))
  q = y ~ /[[:alnum:]_.!~*\47()-]/ ? q y : q sprintf("%%%02X", z[y])
  print q}' "$1"
}

Пример:

value=$(encodeURIComponent "$2")

Источник

1 голос
/ 25 декабря 2013

Это ksh-версия ответа orwellophile, содержащая функции rawurlencode и rawurldecode (ссылка: Как кодировать данные для команды curl? ). У меня недостаточно репутации для добавления комментария, поэтому новое сообщение ..

#!/bin/ksh93

function rawurlencode
{
    typeset string="${1}"
    typeset strlen=${#string}
    typeset encoded=""

    for (( pos=0 ; pos<strlen ; pos++ )); do
        c=${string:$pos:1}
        case "$c" in
            [-_.~a-zA-Z0-9] ) o="${c}" ;;
            * )               o=$(printf '%%%02x' "'$c")
        esac
        encoded+="${o}"
    done
    print "${encoded}"
}

function rawurldecode
{
    printf $(printf '%b' "${1//%/\\x}")
}

print $(rawurlencode "C++")     # --> C%2b%2b
print $(rawurldecode "C%2b%2b") # --> C++
1 голос
/ 15 августа 2013

Установив php, я использую этот способ:

URL_ENCODED_DATA=`php -r "echo urlencode('$DATA');"`
0 голосов
/ 03 января 2018

Следующее основано на ответе Орвеллофила, но решает многобайтовый ошибка упоминается в комментариях путем установки LC_ALL = C (трюк из vte.sh). Я написал это в виде функции, подходящей PROMPT_COMMAND, потому что вот как я это использую.

print_path_url() {
  local LC_ALL=C
  local string="$PWD"
  local strlen=${#string}
  local encoded=""
  local pos c o

  for (( pos=0 ; pos<strlen ; pos++ )); do
     c=${string:$pos:1}
     case "$c" in
        [-_.~a-zA-Z0-9/] ) o="${c}" ;;
        * )               printf -v o '%%%02x' "'$c"
     esac
     encoded+="${o}"
  done
  printf "\033]7;file://%s%s\007" "${HOSTNAME:-}" "${encoded}"
}
0 голосов
/ 12 апреля 2017

Что будет разбирать URL лучше, чем javascript?

node -p "encodeURIComponent('$url')"
...