Jak urlencode dane dla polecenia curl?

Próbuję napisać skrypt bash do testów, który pobiera parametr i wysyła go przez curl do strony internetowej. Muszę zakodować wartość adresu url, aby upewnić się, że znaki specjalne są przetwarzane prawidłowo. Jak najlepiej to zrobić?

Oto mój podstawowy skrypt do tej pory:

#!/bin/bash
host=${1:?'bad host'}
value=$2
shift
shift
curl -v -d "param=${value}" http://${host}/somepath $@
Author: Mateusz Piotrowski, 2008-11-17

30 answers

Use curl --data-urlencode; from man curl:

Ten wpisuje dane, podobnie jak inne opcje --data z tym wyjątkiem, że wykonuje kodowanie URL. Aby część <data> była zgodna z CGI, powinna zaczynać się od nazwy, po której następuje separator i specyfikacja treści.

Przykładowe użycie:

curl \
    --data-urlencode "paramName=value" \
    --data-urlencode "secondParam=value" \
    http://example.com

Zobacz stronę podręcznika ekranowego aby uzyskać więcej informacji.

To wymaga curl 7.18.0 lub nowszego (wydany w styczniu 2008) . Użyj curl -V, aby sprawdzić, którą wersję masz.

 303
Author: Jacob R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-14 18:41:56

Oto odpowiedź pure BASH.

rawurlencode() {
  local string="${1}"
  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
  echo "${encoded}"    # You can either set a return variable (FASTER) 
  REPLY="${encoded}"   #+or echo the result (EASIER)... or both... :p
}
Można go używać na dwa sposoby:]}
easier:  echo http://url/q?=$( rawurlencode "$args" )
faster:  rawurlencode "$args"; echo http://url/q?${REPLY}

[edytuj]

Oto pasująca funkcja rawurldecode (), która - z całą skromnością - jest niesamowita.

# Returns a string in which the sequences with percent (%) signs followed by
# two hex digits have been replaced with literal characters.
rawurldecode() {

  # This is perhaps a risky gambit, but since all escape characters must be
  # encoded, we can replace %NN with \xNN and pass the lot to printf -b, which
  # will decode hex for us

  printf -v REPLY '%b' "${1//%/\\x}" # You can either set a return variable (FASTER)

  echo "${REPLY}"  #+or echo the result (EASIER)... or both... :p
}

Z dopasowanym zestawem możemy teraz wykonać kilka prostych testów:

$ diff rawurlencode.inc.sh \
        <( rawurldecode "$( rawurlencode "$( cat rawurlencode.inc.sh )" )" ) \
        && echo Matched

Output: Matched

I jeśli naprawdę uważasz, że potrzebujesz zewnętrznego narzędzia (cóż, pójdzie o wiele szybciej, i może zrobić pliki binarne i takie...) Znalazłem to na moim routerze OpenWRT...

replace_value=$(echo $replace_value | sed -f /usr/lib/ddns/url_escape.sed)

Gdzie url_escape.sed był plikiem zawierającym te zasady:

# sed url escaping
s:%:%25:g
s: :%20:g
s:<:%3C:g
s:>:%3E:g
s:#:%23:g
s:{:%7B:g
s:}:%7D:g
s:|:%7C:g
s:\\:%5C:g
s:\^:%5E:g
s:~:%7E:g
s:\[:%5B:g
s:\]:%5D:g
s:`:%60:g
s:;:%3B:g
s:/:%2F:g
s:?:%3F:g
s^:^%3A^g
s:@:%40:g
s:=:%3D:g
s:&:%26:g
s:\$:%24:g
s:\!:%21:g
s:\*:%2A:g
 139
Author: Orwellophile,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-05 05:58:14

Użyj modułu Perla URI::Escape i funkcji uri_escape w drugiej linii skryptu bash:

...

value="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "$2")"
...

Edit: Napraw problemy z cytowaniem, jak zasugerował Chris Johnsen w komentarzach. Dzięki!

 86
Author: dubek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-12 09:39:32

Ze względu na kompletność, wiele rozwiązań wykorzystujących sed lub awk tłumaczy tylko specjalny zestaw znaków i dlatego są dość duże pod względem rozmiaru kodu, a także nie tłumaczą innych znaków specjalnych, które powinny być zakodowane.

Bezpiecznym sposobem na kodowanie urlencode byłoby zakodowanie każdego bajtu - nawet tych, które byłyby dozwolone.

echo -ne 'some random\nbytes' | xxd -plain | tr -d '\n' | sed 's/\(..\)/%\1/g'

Xxd dba o to, aby dane wejściowe były traktowane jako bajty, a nie znaki.

Edit:

Xxd pochodzi z vim-common package w Debianie i byłem tylko na systemie, w którym nie był zainstalowany i nie chciałem go zainstalować. Altornative jest użycie hexdump z pakietu Bsdmainutils w Debianie. Zgodnie z poniższym wykresem, bsdmainutils i Vim-common powinny mieć równe prawdopodobieństwo zainstalowania:

Http://qa.debian.org/popcon-png.php?packages=vim-common%2Cbsdmainutils&show_installed=1&want_legend=1&want_ticks=1

Ale jednak tutaj wersja, która wykorzystuje hexdump zamiast xxd i pozwala uniknąć wywołania tr:

echo -ne 'some random\nbytes' | hexdump -v -e '/1 "%02x"' | sed 's/\(..\)/%\1/g'
 52
Author: josch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-12 20:33:12

Uważam, że jest bardziej czytelny w Pythonie:

encoded_value=$(python -c "import urllib; print urllib.quote('''$value''')")

Potrójne ' zapewnia, że pojedyncze cudzysłowy w wartości nie zaszkodzą. urllib jest w bibliotece standardowej. Działa dla tego szalonego (prawdziwego świata) url:

"http://www.rai.it/dl/audio/" "1264165523944Ho servito il re d'Inghilterra - Puntata 7
 41
Author: sandro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-10 10:26:10

Jeden z wariantów, może być brzydki, ale prosty:

urlencode() {
    local data
    if [[ $# != 1 ]]; then
        echo "Usage: $0 string-to-urlencode"
        return 1
    fi
    data="$(curl -s -o /dev/null -w %{url_effective} --get --data-urlencode "$1" "")"
    if [[ $? != 3 ]]; then
        echo "Unexpected error" 1>&2
        return 2
    fi
    echo "${data##/?}"
    return 0
}

Oto na przykład wersja jednoliniowa (zgodnie z sugestią Bruno):

date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3-
 38
Author: Sergey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-01 23:56:54

Znalazłem następujący fragment przydatny do przyklejenia go do łańcucha wywołań programu, gdzie URI:: Escape może nie być zainstalowany:

perl -p -e 's/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg'

(Źródło )

 27
Author: blueyed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-31 16:27:49

Jeśli chcesz uruchomić GET request i użyć pure curl, po prostu dodaj --get do rozwiązania @Jacob.

Oto przykład:

curl -v --get --data-urlencode "access_token=$(cat .fb_access_token)" https://graph.facebook.com/me/feed
 17
Author: Piotr Czapla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-25 12:37:16

Inną opcją jest użycie jq:

jq -s -R -r @uri

-s (--slurp) odczytuje linie wejściowe do tablicy i -s -R (--slurp --raw-input) wczytuje dane wejściowe do pojedynczego łańcucha. -r (--raw-output) wypisuje zawartość ciągów zamiast liter ciągów JSON.

Lub ten procent-koduje wszystkie bajty:

xxd -p|tr -d \\n|sed 's/../%&/g'
 15
Author: user4669748,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-22 02:38:16

Bezpośredni link do wersji awk: http://www.shelldorado.com/scripts/cmds/urlencode
Używałem go od lat i działa jak urok

:
##########################################################################
# Title      :  urlencode - encode URL data
# Author     :  Heiner Steven ([email protected])
# Date       :  2000-03-15
# Requires   :  awk
# Categories :  File Conversion, WWW, CGI
# SCCS-Id.   :  @(#) urlencode  1.4 06/10/29
##########################################################################
# Description
#   Encode data according to
#       RFC 1738: "Uniform Resource Locators (URL)" and
#       RFC 1866: "Hypertext Markup Language - 2.0" (HTML)
#
#   This encoding is used i.e. for the MIME type
#   "application/x-www-form-urlencoded"
#
# Notes
#    o  The default behaviour is not to encode the line endings. This
#   may not be what was intended, because the result will be
#   multiple lines of output (which cannot be used in an URL or a
#   HTTP "POST" request). If the desired output should be one
#   line, use the "-l" option.
#
#    o  The "-l" option assumes, that the end-of-line is denoted by
#   the character LF (ASCII 10). This is not true for Windows or
#   Mac systems, where the end of a line is denoted by the two
#   characters CR LF (ASCII 13 10).
#   We use this for symmetry; data processed in the following way:
#       cat | urlencode -l | urldecode -l
#   should (and will) result in the original data
#
#    o  Large lines (or binary files) will break many AWK
#       implementations. If you get the message
#       awk: record `...' too long
#        record number xxx
#   consider using GNU AWK (gawk).
#
#    o  urlencode will always terminate it's output with an EOL
#       character
#
# Thanks to Stefan Brozinski for pointing out a bug related to non-standard
# locales.
#
# See also
#   urldecode
##########################################################################

PN=`basename "$0"`          # Program name
VER='1.4'

: ${AWK=awk}

Usage () {
    echo >&2 "$PN - encode URL data, $VER
usage: $PN [-l] [file ...]
    -l:  encode line endings (result will be one line of output)

The default is to encode each input line on its own."
    exit 1
}

Msg () {
    for MsgLine
    do echo "$PN: $MsgLine" >&2
    done
}

Fatal () { Msg "$@"; exit 1; }

set -- `getopt hl "$@" 2>/dev/null` || Usage
[ $# -lt 1 ] && Usage           # "getopt" detected an error

EncodeEOL=no
while [ $# -gt 0 ]
do
    case "$1" in
        -l) EncodeEOL=yes;;
    --) shift; break;;
    -h) Usage;;
    -*) Usage;;
    *)  break;;         # First file name
    esac
    shift
done

LANG=C  export LANG
$AWK '
    BEGIN {
    # We assume an awk implementation that is just plain dumb.
    # We will convert an character to its ASCII value with the
    # table ord[], and produce two-digit hexadecimal output
    # without the printf("%02X") feature.

    EOL = "%0A"     # "end of line" string (encoded)
    split ("1 2 3 4 5 6 7 8 9 A B C D E F", hextab, " ")
    hextab [0] = 0
    for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0
    if ("'"$EncodeEOL"'" == "yes") EncodeEOL = 1; else EncodeEOL = 0
    }
    {
    encoded = ""
    for ( i=1; i<=length ($0); ++i ) {
        c = substr ($0, i, 1)
        if ( c ~ /[a-zA-Z0-9.-]/ ) {
        encoded = encoded c     # safe character
        } else if ( c == " " ) {
        encoded = encoded "+"   # special handling
        } else {
        # unsafe character, encode it as a two-digit hex-number
        lo = ord [c] % 16
        hi = int (ord [c] / 16);
        encoded = encoded "%" hextab [hi] hextab [lo]
        }
    }
    if ( EncodeEOL ) {
        printf ("%s", encoded EOL)
    } else {
        print encoded
    }
    }
    END {
        #if ( EncodeEOL ) print ""
    }
' "$@"
 14
Author: MatthieuP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-09 00:17:39

To może być najlepsze:

after=$(echo -e "$before" | od -An -tx1 | tr ' ' % | xargs printf "%s")
 12
Author: chenzhiwei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-12 03:08:17
url=$(echo "$1" | sed -e 's/%/%25/g' -e 's/ /%20/g' -e 's/!/%21/g' -e 's/"/%22/g' -e 's/#/%23/g' -e 's/\$/%24/g' -e 's/\&/%26/g' -e 's/'\''/%27/g' -e 's/(/%28/g' -e 's/)/%29/g' -e 's/\*/%2a/g' -e 's/+/%2b/g' -e 's/,/%2c/g' -e 's/-/%2d/g' -e 's/\./%2e/g' -e 's/\//%2f/g' -e 's/:/%3a/g' -e 's/;/%3b/g' -e 's//%3e/g' -e 's/?/%3f/g' -e 's/@/%40/g' -e 's/\[/%5b/g' -e 's/\\/%5c/g' -e 's/\]/%5d/g' -e 's/\^/%5e/g' -e 's/_/%5f/g' -e 's/`/%60/g' -e 's/{/%7b/g' -e 's/|/%7c/g' -e 's/}/%7d/g' -e 's/~/%7e/g')

To zakoduje łańcuch w $1 i wyświetli go w $ url. chociaż nie musisz umieszczać go w var, jeśli chcesz. BTW nie wlaczylem sed dla tab myslalem ze zamieni to w spacje

 9
Author: manoflinux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-11 13:27:13

Dla tych z Was, którzy szukają rozwiązania, które nie potrzebuje Perla, oto rozwiązanie, które potrzebuje tylko hexdump i awk:

url_encode() {
 [ $# -lt 1 ] && { return; }

 encodedurl="$1";

 # make sure hexdump exists, if not, just give back the url
 [ ! -x "/usr/bin/hexdump" ] && { return; }

 encodedurl=`
   echo $encodedurl | hexdump -v -e '1/1 "%02x\t"' -e '1/1 "%_c\n"' |
   LANG=C awk '
     $1 == "20"                    { printf("%s",   "+"); next } # space becomes plus
     $1 ~  /0[adAD]/               {                      next } # strip newlines
     $2 ~  /^[a-zA-Z0-9.*()\/-]$/  { printf("%s",   $2);  next } # pass through what we can
                                   { printf("%%%s", $1)        } # take hex value of everything else
   '`
}

Zszyte z kilku miejsc w sieci i trochę lokalnych prób i błędów. Działa świetnie!

 7
Author: Louis Marascio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-27 19:28:54

Używanie php ze skryptu powłoki:

value="http://www.google.com"
encoded=$(php -r "echo rawurlencode('$value');")
# encoded = "http%3A%2F%2Fwww.google.com"
echo $(php -r "echo rawurldecode('$encoded');")
# returns: "http://www.google.com"
  1. http://www.php.net/manual/en/function.rawurlencode.php
  2. http://www.php.net/manual/en/function.rawurldecode.php
 6
Author: Darren Weber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-31 23:10:59

Uni2ascii jest bardzo przydatny:

$ echo -ne '你好世界' | uni2ascii -aJ
%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C
 6
Author: kev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-26 08:48:57

Jeśli nie chcesz polegać na perlu, możesz również użyć sed. Jest to trochę bałagan, ponieważ każda postać musi być uniknięta indywidualnie. Utwórz plik o następującej zawartości i nazwij go urlencode.sed

s/%/%25/g
s/ /%20/g
s/ /%09/g
s/!/%21/g
s/"/%22/g
s/#/%23/g
s/\$/%24/g
s/\&/%26/g
s/'\''/%27/g
s/(/%28/g
s/)/%29/g
s/\*/%2a/g
s/+/%2b/g
s/,/%2c/g
s/-/%2d/g
s/\./%2e/g
s/\//%2f/g
s/:/%3a/g
s/;/%3b/g
s//%3e/g
s/?/%3f/g
s/@/%40/g
s/\[/%5b/g
s/\\/%5c/g
s/\]/%5d/g
s/\^/%5e/g
s/_/%5f/g
s/`/%60/g
s/{/%7b/g
s/|/%7c/g
s/}/%7d/g
s/~/%7e/g
s/      /%09/g

Aby go użyć, wykonaj następujące czynności.

STR1=$(echo "https://www.example.com/change&$ ^this to?%checkthe@-functionality" | cut -d\? -f1)
STR2=$(echo "https://www.example.com/change&$ ^this to?%checkthe@-functionality" | cut -d\? -f2)
OUT2=$(echo "$STR2" | sed -f urlencode.sed)
echo "$STR1?$OUT2"

To podzieli łańcuch na część, która wymaga kodowania, a część, która jest w porządku, zakoduje część, która jej potrzebuje, a następnie połączy się z powrotem.

Możesz umieścić to w skrypcie sh dla wygody, może wziąć parametr do Zakoduj, umieść go na swojej ścieżce i wtedy możesz po prostu wywołać:

urlencode https://www.exxample.com?isThisFun=HellNo

źródło

 6
Author: Jay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-26 08:07:15

Pytanie dotyczy robienia tego w bash i nie ma potrzeby stosowania Pythona ani Perla, ponieważ w rzeczywistości istnieje jedno polecenie, które robi dokładnie to, co chcesz - "urlencode".

value=$(urlencode "${2}")

Jest to również znacznie lepsze, ponieważ powyższa odpowiedź Perla, na przykład, nie koduje wszystkich znaków poprawnie. Spróbuj z długą kreską, którą otrzymujesz z programu Word, a otrzymasz złe kodowanie.

Uwaga, musisz zainstalować" gridsite-clients " aby dostarczyć to polecenie.

 5
Author: Dylan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-14 11:55:29

Możesz emulować javascript encodeURIComponent w Perlu. Oto Komenda:

perl -pe 's/([^a-zA-Z0-9_.!~*()'\''-])/sprintf("%%%02X", ord($1))/ge'

Możesz ustawić to jako alias bash w .bash_profile:

alias encodeURIComponent='perl -pe '\''s/([^a-zA-Z0-9_.!~*()'\''\'\'''\''-])/sprintf("%%%02X",ord($1))/ge'\'

Teraz możesz przejść do encodeURIComponent:

$ echo -n 'hèllo wôrld!' | encodeURIComponent
h%C3%A8llo%20w%C3%B4rld!
 5
Author: Klaus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-20 21:08:51

Prosta opcja PHP:

echo 'part-that-needs-encoding' | php -R 'echo urlencode($argn);'
 5
Author: Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-26 09:07:20

Inne podejście php:

echo "encode me" | php -r "echo urlencode(file_get_contents('php://stdin'));"
 4
Author: jan halfar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-18 09:13:49

Oto wersja węzła:

uriencode() {
  node -p "encodeURIComponent('${1//\'/\\\'}')"
}
 4
Author: davidchambers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-06 07:49:18

Ruby, dla kompletności

value="$(ruby -r cgi -e 'puts CGI.escape(ARGV[0])' "$2")"
 3
Author: k107,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-19 23:45:26

Oto rozwiązanie Bash, które nie wywołuje żadnych zewnętrznych programów:

uriencode() {
  s="${1//'%'/%25}"
  s="${s//' '/%20}"
  s="${s//'"'/%22}"
  s="${s//'#'/%23}"
  s="${s//'$'/%24}"
  s="${s//'&'/%26}"
  s="${s//'+'/%2B}"
  s="${s//','/%2C}"
  s="${s//'/'/%2F}"
  s="${s//':'/%3A}"
  s="${s//';'/%3B}"
  s="${s//'='/%3D}"
  s="${s//'?'/%3F}"
  s="${s//'@'/%40}"
  s="${s//'['/%5B}"
  s="${s//']'/%5D}"
  printf %s "$s"
}
 3
Author: davidchambers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-23 21:01:03

Oto funkcja POSIX do tego celu:

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"
}

Przykład:

value=$(encodeURIComponent "$2")

Źródło

 2
Author: Steven Penny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-31 05:14:25

Oto jednolinijkowa konwersja przy użyciu Lua, podobna do odpowiedzi blueyed z wyjątkiem wszystkich znaków bez kodu RFC 3986 pozostawionych bez kodu (jak ta odpowiedź):

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

Dodatkowo może być konieczne upewnienie się, że nowe linie w Twoim łańcuchu są konwertowane z LF na CRLF, w takim przypadku możesz wstawić gsub("\r?\n", "\r\n") w łańcuchu przed kodowaniem procentowym.

Oto wariant, który w niestandardowym stylu aplikacji / x-www-form-urlencoded , czy ta normalizacja nowej linii, jak również spacje kodujące jako " + "zamiast" %20 "( które prawdopodobnie można by dodać do fragmentu Perla przy użyciu podobnej techniki).

url=$(echo 'print((arg[1]:gsub("\r?\n", "\r\n"):gsub("([^%w%-%.%_%~ ]))",function(c)return("%%%02X"):format(c:byte())end):gsub(" ","+"))' | lua - "$1")
 2
Author: Stuart P. Bentley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26

Po zainstalowaniu php używam w ten sposób:

URL_ENCODED_DATA=`php -r "echo urlencode('$DATA');"`
 1
Author: ajaest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-15 12:04:33

To jest wersja ksh odpowiedzi orwellophile ' a zawierająca funkcje rawurlencode i rawurldecode (link: Jak urlencode danych dla polecenia curl?). Nie mam dość rep, aby dodać komentarz, stąd nowy post..

#!/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
Author: Ray Burgemeestre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:20

Oto moja wersja dla busybox ash shell dla systemu embedded, pierwotnie zaadoptowałem wariant Orwellophile ' a:

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}"
}
 1
Author: nulleight,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-31 10:45:24

Poniższy tekst opiera się na odpowiedzi Orwella, ale rozwiązuje wielobajt błąd wymieniony w komentarzach przez ustawienie LC_ALL = C (trick z vte.sh). Napisałem go w formie funkcji odpowiedniej PROMPT_COMMAND, ponieważ tak go używam.

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
Author: Per Bothner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-03 04:56:48

Co lepiej analizuje adresy URL niż javascript?

node -p "encodeURIComponent('$url')"
 -1
Author: Nestor Urquiza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-12 17:42:15