curl 명령을 위해 데이터를 urlencode하는 방법은 무엇입니까?


319

테스트를 위해 매개 변수를 사용하고 curl을 통해 웹 사이트로 보내는 bash 스크립트를 작성하려고합니다. 특수 문자가 올바르게 처리되도록 값을 URL 인코딩해야합니다. 가장 좋은 방법은 무엇입니까?

지금까지 내 기본 스크립트는 다음과 같습니다.

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


답변:


395

사용 curl --data-urlencode; 부터 man curl:

이것은 --dataURL 인코딩을 수행한다는 점을 제외 하고 다른 옵션과 마찬가지로 데이터를 게시합니다 . CGI 규격을 준수하려면 <data>부품 이름과 구분 기호 및 내용 사양으로 시작해야합니다.

사용법 예 :

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

자세한 내용 은 매뉴얼 페이지 를 참조하십시오.

curl 7.18.0 이상 (2008 년 1 월 릴리스) 이 필요합니다 . 사용 curl -V중인 버전을 확인하는 데 사용하십시오 .

쿼리 문자열을 인코딩 할 수도 있습니다 .

curl -G \
    --data-urlencode "p1=value 1" \
    --data-urlencode "p2=value 2" \
    http://example.com
    # http://example.com?p1=value%201&p2=value%202

5
http POST에서만 작동하는 것 같습니다. 여기 문서 : curl.haxx.se/docs/manpage.html#--data-urlencode
Stan James

82
@StanJames 그렇게 사용하면 curl도 GET 요청에 대한 인코딩을 수행 할 수 있습니다. curl -G --data-urlencode "blah=df ssdf sdf" --data-urlencode "blah2=dfsdf sdfsd " http://whatever.com/whatever
kberg

13
@kberg는 실제로 쿼리 데이터에만 작동합니다. 컬은 '?'를 추가합니다 urlencoded params가 뒤 따릅니다. 일부 URL 접미사 (예 : 일부 문서 ID에 대한 CouchDB GET)를 urlencode하려는 경우 '--data-urlencode'가 작동하지 않습니다.
Bokeh

1
작동하지 않습니다 curl --data-urlencode "description=![image]($url)" www.example.com. 왜 그런지 알아? `
Khurshid Alam

1
@NadavB 탈출 "
BlackJack

179

다음은 순수한 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
}

두 가지 방법으로 사용할 수 있습니다.

easier:  echo http://url/q?=$( rawurlencode "$args" )
faster:  rawurlencode "$args"; echo http://url/q?${REPLY}

[편집]

일치하는 rawurldecode () 함수는 다음과 같습니다.

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

일치 세트를 사용하여 간단한 테스트를 수행 할 수 있습니다.

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

Output: Matched

그리고 정말로 외부 도구가 필요하다고 생각한다면 (더 빨리 가고, 바이너리 파일 등을 할 수 있습니다 ...) OpenWRT 라우터에서 이것을 찾았습니다 ...

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

url_escape.sed는 다음 규칙을 포함하는 파일입니다.

# 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

4
불행히도이 스크립트는 'é'및 '½'과 같은 일부 문자에서 실패하여 각각 'e % FFFFFFFFFFFFFFCCCC'및 '% FFFFFFFFFFFFFFFFC2'를 출력합니다 (문자 당 루프의 b / c).
Matthemattics

1
Bash 4.3.11 (1)에서 작동하지 않습니다. 문자열 Jogging «à l'Hèze»생성 Jogging%20%abà%20l%27Hèze%bb즉 JS로 공급 될 수없는 decodeURIComponent:(
dmcontador

2
첫 번째 코드 블록에서 printf의 마지막 매개 변수는 무엇을 의미합니까? 즉, 왜 큰 따옴표, 작은 따옴표, 달러 기호, 문자 c, 큰 따옴표입니까? 작은 따옴표는합니까?
콜린 프레이저

1
@dmcontador-그것은 겸손한 bash 스크립트 일 뿐이며 멀티 바이트 문자 또는 유니 코드 개념이 없습니다. ń ( \u0144) 과 같은 문자가 보이면 순전히 % 144를 출력하고 ╡ ( \u2561)는 % 2561로 출력합니다. 이에 대한 올바른 원시 코드화 된 답변은 각각 % C5 % 84 % 0A 및 % E2 % 95 % A1입니다.
Orwellophile

1
@ColinFraizer 작은 따옴표는 다음 문자를 숫자 값으로 변환하는 역할을합니다. 심판. pubs.opengroup.org/onlinepubs/9699919799/utilities/…
Sam

94

bash 스크립트의 두 번째 줄에서 Perl의 URI::Escape모듈과 uri_escape기능을 사용하십시오 .

...

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

편집 : 주석에서 Chris Johnsen이 제안한대로 인용 문제를 수정 하십시오 . 감사!


2
URI :: Escape가 설치되지 않았을 수 있습니다.이 경우 대답을 확인하십시오.
blueyed 2009

나는 이것을 사용 echo하고 (use , pipe 및 <>) $ 2에 아포스트로피 또는 큰 따옴표가 포함되어 있어도 작동합니다. 감사!
dubek

9
당신도 함께 echo:value="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "$2")"
Chris Johnsen

1
Chris Johnsen의 버전이 더 좋습니다. 테스트 표현식에 $ {True}가 있고 echo를 통해 이것을 사용하여 uri_escape / Perl 변수 확장이 발생했습니다.
mm2001

1
@ jrw32982 예, 다시 한 번 살펴보면이 작업을 수행 할 수있는 다른 언어가있는 것이 좋습니다. 그것은 현재에 잠겨 아아 내가 할 수있는하다면, 내 downvote을 다시 걸리지 만 것입니다.
thecoshman

69

또 다른 옵션은 jq필터 로 사용 하는 것입니다.

jq -sRr @uri

-R( --raw-input)는 입력 라인을 JSON으로 구문 분석하는 대신 문자열로 취급하고 -sR( --slurp --raw-input)는 입력을 단일 문자열로 읽습니다. -r( --raw-output)는 JSON 문자열 리터럴 대신 문자열의 내용을 출력합니다.

입력이 다른 명령의 출력이 아닌 경우 jq문자열 변수 에 저장할 수 있습니다 .

jq -nr --arg v "my shell string" '$v|@uri'

-n( --null-input)는 입력을 읽지 않고 변수 에 문자열로 --arg name value저장 합니다. 쉘에서 확장을 피하기 위해 작은 따옴표로 묶인 필터 에서 변수를 참조합니다 .valuename$namename

Bash 함수로 감싸 인 다음과 같습니다.

function uriencode { jq -nr --arg v "$1" '$v|@uri'; }

또는이 백분율은 모든 바이트를 인코딩합니다.

xxd -p|tr -d \\n|sed 's/../%&/g'

3
<3 그것은 ... 위로 및 IMO 승인 (해야 그래, 당신은 말할 수 있다면 curl인코딩에 그 작품과 bash는 허용했을 내장 명령이있는 경우 -하지만 jq내가 가진 안락 수준을 달성에서 멀리 해요 그래도 오른쪽에 맞는 것 같아 이 도구)
nhed

5
나와 같은 것을 궁금해하는 사람 @uri은 변수가 아니라 문자열 형식과 이스케이프 처리에 사용되는 리터럴 jq 필터입니다. 자세한 내용은 jq 설명서 를 참조하십시오 (죄송합니다. 직접 링크가 없으며 @uri페이지 에서 검색해야합니다 ...)
ssc

xxd 버전은 내가 찾던 일종입니다. 조금 더러워도 짧고 의존성이 없습니다.
Rian Sanderson

1
URL 인코딩을위한 jq의 샘플 사용법 :printf "http://localhost:8082/" | jq -sRr '@uri'
Ashutosh Jindal

67

완벽을 기하기 위해 많은 문자를 사용 sed하거나 awk특수 문자 세트 만 변환하므로 코드 크기에 따라 크기가 크며 인코딩해야하는 다른 특수 문자도 변환하지 않습니다.

urlencode의 안전한 방법은 모든 단일 바이트를 인코딩하는 것입니다.

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

여기서 xxd는 입력이 문자가 아닌 바이트로 처리되도록주의하고 있습니다.

편집하다:

xxd는 데비안에서 vim-common 패키지와 함께 제공되며 설치되지 않은 시스템에 설치하고 싶지 않았습니다. 대안은 hexdump데비안의 bsdmainutils 패키지에서 사용 하는 것입니다. 다음 그래프에 따르면 bsdmainutils 및 vim-common은 설치 될 가능성이 거의 동일해야합니다.

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

그럼에도 불구하고 여기서는 hexdump대신에 사용 xxd하고 tr전화 를 피할 수 있는 버전이 있습니다 .

echo -ne 'some random\nbytes' | hexdump -v -e '/1 "%02x"' | sed 's/\(..\)/%\1/g'

1
xxd -plain후에 일어날 것입니다 tr -d '\n'!
qdii

3
@qdii 왜? 그것은 개행을 urlencode하는 것을 불가능하게 할뿐만 아니라 xxd에 의해 생성 된 개행을 출력에 잘못 삽입합니다.
josch

1
@ 조쉬. 이것은 명백한 잘못입니다. 첫째, 어떤 \n문자로 변환됩니다 xxd -plain0a. 내 말을 받아들이지 말고 직접 시도해보십시오. echo -n -e '\n' | xxd -plain이것은 당신 tr -d '\n'이 여기에서 쓸모가 없다는 것을 증명합니다. 두 번째 \n이후 에는 불가능합니다. 문자열의 끝에 자체 문자를 추가 하므로 예상대로 공급되지 않지만으로 공급 됩니다 . 그런 다음 로 끝나는 문자열로 변환 하여 사용자에게 적합하지 않습니다. 당신은 그것을 해결하기 위해 추가 할 수 있습니다 . xxd -plainecho foobar\nxxd -plainfoobarfoobar\nxxd -plain0a-necho
qdii

6
@qdii 실제로 -n은 echo에 대해 누락되었지만 xxd호출 은 호출 앞에 속합니다 tr -d. 개행 문자가 foobar로 번역 되도록 거기에 속합니다 xxd. 는 tr -d애프터 xxd전화 xxd가 생산하는 뉴 라인을 제거하는 것입니다. 줄 xxd바꿈 을 생성 할만 큼 foobar가 충분하지 않은 것처럼 보이지만 입력이 길면 줄어 듭니다. 그래서 tr -d필요합니다. 가정과 달리 tr -d입력에서 줄 바꿈을 제거하는 것이 아니라 xxd출력 에서 줄 바꿈을 제거 하는 것이 었습니다 . 줄 바꿈을 입력에 유지하고 싶습니다. 유일한 요점은 에코가 불필요한 줄 바꿈을 추가한다는 것입니다.
josch

1
@qdii와 공격 없음-나는 당신이 echo -n내가 실제로 놓친 것을 제외하고는 당신이 틀렸다고 생각합니다.
josch

62

변형 중 하나는 추악하지만 단순 할 수 있습니다.

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
}

예를 들어 Bruno에서 제안한 것처럼 한 줄짜리 버전이 있습니다 .

date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3-

# If you experience the trailing %0A, use
date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | sed -E 's/..(.*).../\1/'

1
이것이 cURL의 URL 인코딩을 재사용하는 매우 영리한 방법이라고 생각합니다.
solidsnack

13
이것은 절대적으로 훌륭합니다! 사람들이 실제로 얼마나 간단한 지 알 수 있도록 한 줄만 남겨두기를 바랍니다. URL이 결과 인코딩하는 date명령을 ... date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3-(당신은에있는 cut컬의 출력은 쿼리 문자열과 함께 기술적으로 상대 URL이기 때문에, 오프 첫 두 문자.)
브루노 Bronosky

2
@BrunoBronosky 한 줄짜리 변형은 좋지만 인코딩 끝에 "% 0A"를 추가하는 것 같습니다. 사용자는 조심하십시오. 기능 버전에이 문제가없는 것 같습니다.
levigroker

7
%0A마지막에 피하려면 printf대신을 사용하십시오 echo.
kenorb

2
한 라이너는 환상적입니다
Stephen Blum

49

파이썬에서 더 읽기 쉽습니다.

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

트리플 '은 값의 작은 따옴표가 아프지 않도록합니다. urllib은 표준 라이브러리에 있습니다. 이 미친 (실제) URL의 예를 들어 작동합니다.

"http://www.rai.it/dl/audio/" "1264165523944Ho servito il re d'Inghilterra - Puntata 7

2
따옴표와 삼중 인용 부호가있는 특수 문자에 문제가 있었으므로 기본적으로 모든 것이 작동하는 것 같습니다. encode_value = "$ (echo -n"$ {data} "| python -c"import urllib; import sys; sys.stdout. write (urllib.quote (sys.stdin.read ())))) ";
Sanderering 중지 Monica Cellio

파이썬 3 버전은입니다 encoded_value=$(python3 -c "import urllib.parse; print (urllib.parse.quote('''$value'''))").
Creshal

1
python -c 'import urllib, sys; sys.stdout.writelines(urllib.quote_plus(l, safe="/\n") for l in sys.stdin)'인용 문제가 거의 없으며 메모리 / 속도 효율적 이어야 합니다 (확인하지 않았으며,
찡 그리기

2
나중에 코드로 파싱 된 문자열로 sys.argv대체 하는 것보다 참조하는 것이 훨씬 안전 $value합니다. value포함 된 경우 어떻게 ''' + __import__("os").system("rm -rf ~") + '''합니까?
Charles Duffy

2
python -c "import urllib;print urllib.quote(raw_input())" <<< "$data"
Rockallite

30

URI :: Escape가 설치되지 않은 일련의 프로그램 호출에 충실하는 데 유용한 다음 코드를 발견했습니다.

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

( 소스 )


4
나를 위해 일했다. 나는 그것을 perl -lpe ... (문자 ell)로 바꿨다. 이것은 후행 줄 바꿈을 제거하여 목적에 필요했습니다.
JohnnyLambada

2
참고로, 사용이의 역을 수행하는 perl -pe 's/\%(\w\w)/chr hex $1/ge'(소스 unix.stackexchange.com/questions/159253/... )
스리 Sarnobat

2
인코딩해야 할 문자에 따라 perl -pe 's/(\W)/sprintf("%%%02X", ord($1))/ge'문자, 숫자 및 밑줄을 허용하지만 다른 모든 문자는 인코딩하도록 단순화 할 수 있습니다 .
robru

23

GET요청 을 실행 하고 순수한 컬을 사용하려면 --get@Jacob의 솔루션에 추가하십시오 .

예를 들면 다음과 같습니다.

curl -v --get --data-urlencode "access_token=$(cat .fb_access_token)" https://graph.facebook.com/me/feed

15

awk 버전으로 직접 연결되는 링크 : http://www.shelldorado.com/scripts/cmds/urlencode
몇 년 동안 사용해 보니 매력처럼 작동합니다

:
##########################################################################
# Title      :  urlencode - encode URL data
# Author     :  Heiner Steven (heiner.steven@odn.de)
# 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 ""
    }
' "$@"

ASCII 대신 UTF-8 인코딩을 얻는 간단한 변형이 있습니까?
avgvstvs 2016 년

15

이것은 가장 좋은 것일 수 있습니다.

after=$(echo -e "$before" | od -An -tx1 | tr ' ' % | xargs printf "%s")

이것은 두 가지 추가 사항으로 나를 위해 작동합니다. 1. 인수 끝에 줄 바꿈을 추가하지 않으려면 -e를 -n으로 바꾸고 2. printf 문자열에 '%%'를 추가하여 각 쌍 앞에 %를 넣으십시오. 16 진수
Rob Fagen

추가 $에 앞서 브래킷 후 작동 after=$(echo -e ...
로마 Rhrn 네 스테 로프

1
이것이 어떻게 작동하는지 설명하십시오. 이 od명령은 일반적이지 않습니다.
마크 스 토스 버그

이것은 odGNU와 다른 출력 형식을 사용하기 때문에 OS X에서는 작동하지 않습니다 od. 예를 들어 OS X 및 GNU로 printf aa|od -An -tx1 -v|tr \ -인쇄합니다 . OS X 또는 GNU 와 함께 사용할 수 있습니다 . POSIX에는 없지만 동일한 작업을 수행합니다 . -----------61--61--------------------------------------------------------od-61-61odod -An -tx1 -v|sed 's/ */ /g;s/ *$//'|tr \ %|tr -d \\nododxxd -p|sed 's/../%&/g'|tr -d \\nxxdod
nisetama

2
이 방법은 효과가있을 수 있지만 모든 단일 문자를 피합니다
Charlie

11

외부 프로그램을 호출하지 않는 Bash 솔루션은 다음과 같습니다.

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

4
이것은 bash 버전간에 다르게 작동합니다. RHEL 6.9에서 bash는 4.1.2이며 작은 따옴표가 포함됩니다. 데비안 9와 bash 4.4.12는 작은 따옴표로 충분합니다. 작은 따옴표를 제거하면 둘 다 작동합니다. s = "$ {s // ','/ % 2C}"
muni764

1
귀하의 발견을 반영하여 답변을 업데이트했습니다. @ muni764.
davidchambers

그냥 경고 ... 이것은 문자와 같은 것들을 인코딩하지 않습니다á
diogovk

10
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')

$ 1 내부의 문자열을 인코딩하여 $ url로 출력합니다. 원하는 경우 var에 넣을 필요는 없습니다. BTW는 탭을 위해 sed를 포함하지 않았습니다.


5
이것이 권장되는 방법 이 아니라는 느낌이 들었습니다 .
코디 그레이

2
내가 말한 것이 효과가 있고 여러 대본에서 사용 했으므로 내가 언급 한 모든 문자에 대해 효과가 있음을 알기 때문에 귀하의 느낌을 설명하십시오. 따라서 누군가가 내 코드를 사용하지 않는 이유를 설명하고 제목이 펄 스크립트가 아닌 "bash 스크립트의 URLEncode"이므로 펄을 사용하십시오.
manoflinux

때로는 진주 솔루션이 필요하지 않으므로 편리합니다.
Yuval Rimar

3
블랙리스트는 나쁜 습관이므로이 방법을 권장하지 않습니다.
Ekevoo

이것은 고양이 file.txt와 호환되는 가장 친절한 솔루션이었습니다
mrwaim


7

펄이 필요없는 솔루션을 찾는 사람들에게는 hexdump와 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
   '`
}

그물을 가로 지르는 두 곳과 현지 시행 착오에서 함께 바느질되었습니다. 잘 작동합니다!


7

uni2ascii 는 매우 편리합니다.

$ echo -ne '你好世界' | uni2ascii -aJ
%E4%BD%A0%E5%A5%BD%E4%B8%96%E7%95%8C

2
ASCII 범위 내의 문자 , 인용 %-s
부호

7

Perl에 의존하고 싶지 않다면 sed를 사용할 수도 있습니다. 각 캐릭터가 개별적으로 탈출해야하기 때문에 약간 지저분합니다. 다음과 같은 내용으로 파일을 작성하여 호출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

사용하려면 다음을 수행하십시오.

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"

이렇게하면 문자열이 인코딩이 필요한 부분과 괜찮은 부분으로 분할되고 필요한 부분이 인코딩 된 다음 다시 연결됩니다.

편의를 위해 sh 스크립트에 넣을 수 있습니다. 아마도 매개 변수를 사용하여 인코딩하고 경로에 넣은 다음 호출 할 수 있습니다.

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

출처


7

encodeURIComponent펄에서 자바 스크립트를 에뮬레이트 할 수 있습니다 . 명령은 다음과 같습니다.

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

다음에서 이것을 bash 별명으로 설정할 수 있습니다 .bash_profile.

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

이제 다음으로 파이프 할 수 있습니다 encodeURIComponent.

$ echo -n 'hèllo wôrld!' | encodeURIComponent
h%C3%A8llo%20w%C3%B4rld!

6

노드 버전은 다음과 같습니다.

uriencode() {
  node -p "encodeURIComponent('${1//\'/\\\'}')"
}

1
단일 백 슬래시 또는 줄 바꿈과 같이 작은 따옴표 사이에 유효하지 않은 다른 문자가 문자열에 있으면이 중단되지 않습니까?
스튜어트 P. 벤틀리

좋은 지적. Bash에서 문제가있는 모든 문자를 피하는 데 어려움을 겪으면 교체를 직접 수행하고 node완전히 피할 수 있습니다. Bash 전용 솔루션을 게시했습니다. :)
davidchambers

1
페이지에 다른 곳에서 찾을이 변종은 STDIN에서 값을 읽어 인용 문제를 방지 :node -p 'encodeURIComponent(require("fs").readFileSync(0))'
마크 Stosberg

6

문제는 bash에서 이것을하는 것에 관한 것이며 실제로 원하는 것을 수행하는 단일 명령 인 "urlencode"가 있기 때문에 파이썬이나 perl이 필요하지 않습니다.

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

예를 들어 위의 펄 대답이 모든 문자를 올바르게 인코딩하지 않기 때문에 훨씬 좋습니다. Word에서 얻은 긴 대시로 시도하고 잘못된 인코딩을 얻습니다.

이 명령을 제공하려면 "gridsite-clients"가 설치되어 있어야합니다.


1
내 버전의 bash (GNU 3.2)에는 없습니다 urlencode. 어떤 버전을 사용하고 있습니까?
Sridhar Sarnobat

1
4.3.42가 있지만 urlencode 명령은 "gridsite-clients"에서 제공합니다. 설치를 시도하면 괜찮을 것입니다.
Dylan

5
그래서 당신의 대답은 다른 것들이 설치되어있는 것 (python, perl, lua, ...)보다 낫지 않습니다
Cyrille Pontvieux

전체 언어 (및 라이브러리) 대신 단일 유틸리티 만 설치하면된다는 점을 제외하고는 매우 간단하고 명확하게 작동합니다.
Dylan

이 명령을 제공하는 패키지 / 프로젝트 페이지의 첫 번째 링크가 유용했을 것입니다.
도론 베하르

6

간단한 PHP 옵션 :

echo 'part-that-needs-encoding' | php -R 'echo urlencode($argn);'

4

완전성을위한 루비

value="$(ruby -r cgi -e 'puts CGI.escape(ARGV[0])' "$2")"

4

또 다른 PHP 접근법 :

echo "encode me" | php -r "echo urlencode(file_get_contents('php://stdin'));"

2
echo개행 문자 (hex 0xa)를 추가합니다 . 이를 중지하려면을 사용하십시오 echo -n.
Mathew Hall

3

다음은 임베디드 시스템 용 busybox ash shell의 버전입니다. 원래 Orwellophile의 변형을 채택했습니다.

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

2

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

출처


2

다음과 유사한 루아 사용하여 한 줄 변환의 의 blueyed 답을 모두 제외하고는 3986 개 예약되지 않은 문자는 RFC (같은 인코딩되지 않은 왼쪽 이 답변 ) :

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

1

PHP를 설치하면 다음과 같이 사용됩니다.

URL_ENCODED_DATA=`php -r "echo urlencode('$DATA');"`

1

이것은 rawurlencode 및 rawurldecode 함수를 포함하는 orwellophile의 ksh 버전입니다 (링크 : curl 명령을 위해 데이터를 urlencode하는 방법? ). 의견을 게시 할 담당자가 충분하지 않으므로 새 게시물입니다.

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

자바 스크립트보다 URL을 더 잘 구문 분석하는 것은 무엇입니까?

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

op 질문 범위를 벗어났습니다. 강타하지 말고 말리십시오. 노드를 사용할 수 있으면 확실히 잘 작동합니다.
Cyrille Pontvieux

왜 파이썬 / 펄이 아닌 다운 투표를합니까? 또한 이것이 "curl 명령을 위해 데이터를 urlencode하는 방법?"이라는 원래의 질문에 어떻게 응답하지 않습니까? 이것은 bash 스크립트에서 사용할 수 있으며 결과는 curl 명령에 제공 될 수 있습니다.
Nestor Urquiza

나는 다른 사람들도 투표하지 않았다. 문제는 bash 스크립트 에서이 작업을 수행하는 방법이었습니다. node / js, python 또는 perl과 같은 다른 언어를 사용하는 경우 curl을 직접 사용할 필요가 없습니다.
Cyrille Pontvieux

2
다운 보트를 귀찮게하지 않았지만이 명령의 문제점은 자바 스크립트에서 사용하기 위해 데이터를 올바르게 이스케이프해야한다는 것입니다. 작은 따옴표와 역 슬래시 광기로 시도해보십시오. 노드를 사용하려면 stdin에서 다음과 같은 내용을 더 잘 읽으십시오node -p 'encodeURIComponent(require("fs").readFileSync(0))'
Michael Krelin-hacker

1
STDIN에서 데이터를 파이프하는 경우 @ MichaelKrelin-hacker의 솔루션에주의하십시오. 후행 줄 바꿈을 포함하지 않아야합니다. 예를 들어, echo | ...잘못된 반면 echo -n | ...개행은 표시되지 않습니다.
마크 스 토스 버그

0

다음은 Orwellophile의 답변을 기반으로하지만 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}"
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.