Giải mã mã hóa URL (mã hóa phần trăm)


100

Tôi muốn giải mã mã hóa URL, có công cụ tích hợp nào để thực hiện việc này không hoặc có ai có thể cung cấp cho tôi sedmã để thực hiện việc này không?

Tôi đã tìm kiếm một chút thông qua unix.stackexchange.com và trên internet nhưng tôi không thể tìm thấy bất kỳ công cụ dòng lệnh nào để giải mã mã hóa url.

Những gì tôi muốn làm chỉ đơn giản là tại chỗ chỉnh sửa một txttập tin để:

  • %21 trở thành !
  • %23 trở thành #
  • %24 trở thành $
  • %26 trở thành &
  • %27 trở thành '
  • %28 trở thành (
  • %29 trở thành )

Và như vậy.


Câu trả lời:


107

Tìm thấy những lớp Python này làm những gì bạn muốn:

$ alias urldecode='python -c "import sys, urllib as ul; \
    print ul.unquote_plus(sys.argv[1])"'

$ alias urlencode='python -c "import sys, urllib as ul; \
    print ul.quote_plus(sys.argv[1])"'

Thí dụ

$ urldecode 'q+werty%3D%2F%3B'
q werty=/;

$ urlencode 'q werty=/;'
q+werty%3D%2F%3B

Người giới thiệu


Tôi biết điều này rất muộn, nhưng có cách nào tôi có thể làm điều này với chỉnh sửa tại chỗ không?
DisplayName

@DisplayName - nghe có vẻ như một Q mới đối với tôi. Tôi muốn hỏi nó, và tham khảo cái này.
slm

15
phát trực tuyến:cat your_lovely_file.csv| python -c "import sys, urllib as ul; [sys.stdout.write(ul.quote_plus(l)) for l in sys.stdin]"
kirill_igum

5
Lưu ý rằng đây là Python 2; trên các hệ thống có python3 mặc định, điều này sẽ dẫn đến lỗi. Thay đổi pythonđể python2giúp đỡ.
Ivan Kolmychek

4
Đối với python3bạn có thể sử dụng import urllib.parse as ulthay vì import urllib as ul.
ibotty

61

quyến rũ

Hãy thử dòng lệnh sau:

$ sed 's@+@ @g;s@%@\\x@g' file | xargs -0 printf "%b"

hoặc thay thế sau bằng cách sử dụng echo -e:

$ sed -e's/%\([0-9A-F][0-9A-F]\)/\\\\\x\1/g' file | xargs echo -e

Lưu ý: Cú pháp trên có thể không chuyển đổi +thành dấu cách và có thể ăn tất cả các dòng mới.


Bạn có thể định nghĩa nó là bí danh và thêm nó vào các tệp RC shell của bạn :

$ alias urldecode='sed "s@+@ @g;s@%@\\\\x@g" | xargs -0 printf "%b"'

Sau đó, mỗi khi bạn cần, chỉ cần đi với:

$ echo "http%3A%2F%2Fwww" | urldecode
http://www

Bash

Khi viết kịch bản, bạn có thể sử dụng cú pháp sau:

input="http%3A%2F%2Fwww"
decoded=$(printf '%b' "${input//%/\\x}")

Tuy nhiên, cú pháp trên sẽ không xử lý +chính xác dấu cộng ( ), vì vậy bạn phải thay thế chúng bằng dấu cách sed.

Bạn cũng có thể sử dụng các chức năng urlencode()urldecode()chức năng sau:

urlencode() {
    # urlencode <string>
    local length="${#1}"
    for (( i = 0; i < length; i++ )); do
        local c="${1:i:1}"
        case $c in
            [a-zA-Z0-9.~_-]) printf "$c" ;;
            *) printf '%%%02X' "'$c" ;;
        esac
    done
}

urldecode() {
    # urldecode <string>

    local url_encoded="${1//+/ }"
    printf '%b' "${url_encoded//%/\\x}"
}

Lưu ý rằng ở trên urldecode()giả định dữ liệu không chứa dấu gạch chéo ngược.

Đây là phiên bản tương tự của Joel được tìm thấy tại: https://github.com/sixarm/urldecode.sh


bash + xxd

Hàm Bash với xxdcông cụ:

urlencode() {
  local length="${#1}"
  for (( i = 0; i < length; i++ )); do
    local c="${1:i:1}"
    case $c in
      [a-zA-Z0-9.~_-]) printf "$c" ;;
    *) printf "$c" | xxd -p -c1 | while read x;do printf "%%%s" "$x";done
  esac
done
}

Tìm thấy trong tập tin chính của cdown , cũng tại stackoverflow .


PHP

Sử dụng PHP bạn có thể thử lệnh sau:

$ echo oil+and+gas | php -r 'echo urldecode(fgets(STDIN));' // Or: php://stdin
oil and gas

hoặc chỉ:

php -r 'echo urldecode("oil+and+gas");'

Sử dụng -Rcho đầu vào nhiều dòng.


Perl

Trong Perl bạn có thể sử dụng URI::Escape.

decoded_url=$(perl -MURI::Escape -e 'print uri_unescape($ARGV[0])' "$encoded_url")

Hoặc để xử lý tệp:

perl -i -MURI::Escape -e 'print uri_unescape($ARGV[0])' file

ôi

Hãy thử giải pháp anon :

awk -niord '{printf RT?$0chr("0x"substr(RT,2)):$0}' RS=%..

Lưu ý: Tham số -ndành riêng cho GNU awk.

Xem: Sử dụng awk printf để văn bản urldecode .

giải mã tên tập tin

Nếu bạn cần xóa mã hóa url khỏi tên tệp, hãy sử dụng deurlnamecông cụ từ renameutils(ví dụ deurlname *.*).

Xem thêm:


Liên quan:


1
awk: Vì điều này sử dụng hàm thư viện, chr()nên có khả năng cao nó sẽ chỉ hoạt động trên GNU awk ( gawk). Tuy nhiên, trong trường hợp này, hầu như không có bất kỳ tương đương nào cho POSIX awk, bởi vì -ntùy chọn (cho phép các đối số không thập phân) awk đặc sản của GNU .
cú pháp

sedMã đầu tiên của bạn cung cấp cho tôi xargs: argument line too longmột tệp có ≥2164 dòng.
Sparhawk

2
Các giải pháp của bạn liên quan đến printfviệc không tính đến việc url có thể chứa các dấu hiệu phần trăm đã thoát như thế nào %25. Bạn chuyển những thứ này cho printf mà không thoát chúng cho printf với một dấu phần trăm khác như thế nào %%.
josch

1
Phiên bản bash yêu cầu local LC_ALL=Cở trên cùng, nếu không, tất cả các ký tự rộng (ví dụ: tiếng Nhật, tiếng Trung, v.v.) không được chia thành các byte đúng cách.
Phernost


18

Có một hàm dựng sẵn cho thư viện chuẩn Python. Trong Python 2, nó urllib.unquote.

decoded_url=$(python2 -c 'import sys, urllib; print urllib.unquote(sys.argv[1])' "$encoded_url")

Hoặc để xử lý tệp:

python2 -c 'import sys, urllib; print urllib.unquote(sys.stdin.read())' <file >file.new &&
mv -f file.new file

Trong Python 3, nó urllib.parse.unquote.

decoded_url=$(python3 -c 'import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))' "$encoded_url")

Hoặc để xử lý tệp:

python3 -c 'import sys, urllib; print(urllib.parse.unquote(sys.stdin.read()))' <file >file.new &&
mv -f file.new file

Trong Perl bạn có thể sử dụng URI::Escape.

decoded_url=$(perl -MURI::Escape -e 'print uri_unescape($ARGV[0])' "$encoded_url")

Hoặc để xử lý tệp:

perl -i -MURI::Escape -e 'print uri_unescape($ARGV[0])' file

Nếu bạn muốn sử dụng các công cụ di động POSIX, thật khó xử, bởi vì ứng cử viên nghiêm túc duy nhất là awk, không phân tích các số thập lục phân. Xem Sử dụng awk printf để văn bản urldecode cho các ví dụ với các triển khai awk phổ biến, bao gồm BusyBox.


10

Nếu bạn muốn sử dụng một sedlệnh đơn giản , thì hãy sử dụng như sau:

sed -e 's/%21/!/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'

Nhưng sẽ thuận tiện hơn khi tạo một tập lệnh như (nói sedscript):

s/%21/!/g
s/%23/#/g
s/%24/$/g
s/%26/\&/g
s/%27/'/g
s/%28/(/g
s/%29/)/g

Sau đó chạy sed -f sedscript < old > new, sẽ xuất ra như bạn muốn.


Để dễ dàng, lệnh urlencodecũng có sẵn trong gridsite-clientsgói có thể được cài đặt từ (bởi sudo apt-get install gridsite-clientstrong hệ thống Ubuntu / Debian).

TÊN

    urlencode - chuyển đổi chuỗi thành hoặc từ dạng được mã hóa URL
TÓM TẮC

    urlencode [-m|-d] string [string ...]

SỰ MIÊU TẢ

    urlencode mã hóa chuỗi theo RFC 1738.

    Đó là, các ký tự A- Z a- z 0- 9 . _-được chuyển qua không thay đổi, nhưng tất cả các ký tự khác được biểu thị dưới dạng% HH, trong đó HH là biểu diễn ASCII thập lục phân hai chữ số của chúng. Ví dụ: URL http://www.gridpp.ac.uk/trở thànhhttp%3A%2F%2Fwww.gridpp.ac.uk%2F

    urlencodechuyển đổi từng ký tự trong tất cả các chuỗi được đưa ra trên dòng lệnh. Nếu nhiều chuỗi được đưa ra, chúng được nối với các khoảng cách trước khi chuyển đổi.

LỰA CHỌN
    -m
      Thay vì chuyển đổi hoàn toàn, hãy thực hiện "mã hóa URL nhẹ" của GridSite trong đó AZ az 0-9. = - _ @ và / được chuyển qua không thay đổi. Điều này dẫn đến các chuỗi dễ đọc hơn một chút nhưng ứng dụng phải được chuẩn bị để tạo hoặc mô phỏng các thư mục được ngụ ý bởi bất kỳ dấu gạch chéo nào.
    -d
      Thực hiện giải mã URL thay vì mã hóa, theo RFC 1738. Các chuỗi% HH và% hh được chuyển đổi và các ký tự khác được chuyển qua không được sửa đổi, ngoại trừ +được chuyển đổi sang không gian.

Ví dụ về giải mã URL:

$ urlencode -d "http%3a%2f%2funix.stackexchange.com%2f"
http://unix.stackexchange.com/

$ urlencode -d "Example: %21, %22, . . . , %29 etc"
Example: !, ", . . . , ) etc

Để được hướng dẫn về sed chuyến thăm
Pandya

4
Đây là một giải pháp tồi, bởi vì nó đòi hỏi phải mã hóa mọi nhân vật. Vấn đề này được minh họa bằng mã của bạn thiếu %20chuỗi thoát thường được sử dụng .
Vượt qua

@Overv Tôi vừa sửa đổi
Pandya

Ngoài ra, bạn có thể muốn kiểm tra lại những gì s/%26/&/gkhông. (Tôi đã sửa nó.)
G-Man

9

Perl một lớp lót:

$ perl -pe 's/\%(\w\w)/chr hex $1/ge'

Thí dụ:

$ echo '%21%22' |  perl -pe 's/\%(\w\w)/chr hex $1/ge'
!"

1
Câu trả lời này hấp dẫn khi bạn không muốn đối phó với việc cài đặt các mô-đun perl.
Sridhar Sarnobat

1
Chỉ có một hoạt động thanh lịch cho tôi trên MacOS.
Qix


7

Tôi không thể nhận xét về câu trả lời tốt nhất trong chủ đề này , vì vậy đây là của tôi.

Cá nhân, tôi sử dụng các bí danh này để mã hóa và giải mã URL:

alias urlencode='python -c "import urllib, sys; print urllib.quote(  sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1])"'

alias urldecode='python -c "import urllib, sys; print urllib.unquote(sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1])"'

Cả hai lệnh đều cho phép bạn chuyển đổi dữ liệu, được truyền dưới dạng đối số dòng lệnh hoặc đọc nó từ đầu vào tiêu chuẩn , bởi vì cả hai dòng đều kiểm tra xem có đối số dòng lệnh (thậm chí là trống) và xử lý chúng hay chỉ đọc đầu vào tiêu chuẩn.


cập nhật 2017-05-23 (mã hóa gạch chéo)

Đáp lại bình luận của @ Bevor.

Nếu bạn cũng cần mã hóa dấu gạch chéo, chỉ cần thêm một đối số thứ hai trống vào hàm trích dẫn, thì dấu gạch chéo cũng sẽ được mã hóa.

Vì vậy, cuối cùng urlencode bí danh trong bash trông như thế này:

alias urlencode='python -c "import urllib, sys; print urllib.quote(sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()[0:-1], \"\")"'

Thí dụ

$ urlencode "Проба пера/Pen test"
%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test

$ echo "Проба пера/Pen test" | urlencode
%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test

$ urldecode %D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test
Проба пера/Pen test

$ echo "%D0%9F%D1%80%D0%BE%D0%B1%D0%B0%20%D0%BF%D0%B5%D1%80%D0%B0%2FPen%20test" | urldecode
Проба пера/Pen test

$ urlencode "Проба пера/Pen test" | urldecode
Проба пера/Pen test

$ echo "Проба пера/Pen test" | urlencode | urldecode
Проба пера/Pen test

1
Không mã hóa dấu gạch chéo.
Bevor

@Bevor: Ví dụ?
DIG MBL

Thêm một dấu gạch chéo vào urlencode "р р р р р
Bevor

1
@Bevor: Bạn nói đúng. Cảm ơn bình luận của bạn. Tôi cũng sẽ thay đổi câu trả lời của tôi để phản ánh nhận xét của bạn trong đó.
DIG mbl

4

Và một cách tiếp cận Perl khác:

#!/usr/bin/env perl
use URI::Encode;
my $uri     = URI::Encode->new( { encode_reserved => 0 } );
while (<>) {

    print $uri->decode($_)
}

Bạn sẽ cần phải cài đặt các URI::Encodemô-đun. Trên Debian của tôi, tôi chỉ có thể chạy

sudo apt-get install liburi-encode-perl

Sau đó, tôi chạy đoạn script trên trên một tệp thử nghiệm có chứa:

http://foo%21asd%23asd%24%26asd%27asd%28asd%29

Kết quả là (tôi đã lưu tập lệnh dưới dạng foo.pl):

$ ./foo.pl
http://foo!asd#asd$&asd'asd(asd)

3

Một câu trả lời trong (chủ yếu là Posix):

$ input='%21%22'
$ printf "`printf "%s\n" "$input" | sed -e 's/+/ /g' -e 's/%\(..\)/\\\\x\1/g'`"
!"

Giải trình:

  • -e 's/+/ /gbiến đổi từng +không gian (như được mô tả trong định mức mã hóa url)
  • -e 's/%\(..\)/\\\\x\1/g'biến đổi từng %XXtrong \\xXX. Thông báo một trong những \sẽ được loại bỏ bằng cách trích dẫn quy tắc.
  • Printf bên trong chỉ ở đó để chuyển đầu vào cho sed. Chúng tôi có thể thay thế nó bằng bất kỳ cơ chế nào khác
  • Printf bên ngoài diễn giải \\xXXtrình tự và kết quả hiển thị.

Biên tập:

%phải luôn được diễn giải trong các URL, nên có thể đơn giản hóa câu trả lời này. Ngoài ra, tôi nghĩ rằng nó là sạch hơn để sử dụng xargsthay vì backquote (nhờ @josch).

$ input='%21%22+%25'
$ printf "%s\n" "$input" | sed -e 's/+/ /g; s/%/\\x/g' | xargs -0 printf
!" %

Thật không may, (như @josch nhận thấy) không có giải pháp nào trong số các giải pháp này tuân thủ Posix vì \xtrình tự thoát không được xác định trong Posix.


Chào mừng bạn đến với U & L. Có lẽ bạn có thể giải thích câu trả lời này và cách nó hoạt động. Chúng tôi thường thích câu trả lời của chúng tôi ở dạng dài với các chi tiết, không chỉ là đoạn mã.
slm

Tôi thực sự thích câu trả lời này vì nó toàn diện, di động và không yêu cầu các chương trình bên ngoài nặng hơn như perl hoặc python. Hoạt động tốt cho tôi.
Steve Wills

1
Giải pháp tuyệt vời. Và thậm chí ngắn hơn và thông minh hơn : ... | sed 's/+/ /g;s/%\(..\)/\\\\x\1/g'. Các -etùy chọn có thể được bỏ qua ở đây trên thực tế ...
Lỗi Cú pháp

1
@josch Bạn nói đúng, printflà tích hợp sẵn dashvà nó không nhận ra \xlối thoát. Bạn có thể sử dụng /usr/bin/printfthay vì printfđể làm cho nó hoạt động. Thông thường, bạn sẽ có thể sử dụng command printf, nhưng nó dường như không hoạt động như bình thường. Nó tiếp tục sử dụng tích hợp.
Jérôme Pouiller

1
@Jezz thực sự hỗ trợ cho việc \xtrốn thoát không phải là một phần của POSIX: pubs.opengroup.org/onlinepub/9699919799/utilities/printf.html Trong các thử nghiệm của tôi, tôi đã thấy một vấn đề khác. Bạn có thể muốn thay thế ..regex của mình bởi [a-zA-Z0-9][a-zA-Z0-9]vì nếu không, cách nhập như '%%%' sẽ không thành công. Tôi cũng đã thêm s/%/%%/gvào cuối để đảm bảo thoát tỷ lệ phần trăm cho printf.
josch

1

Chỉ vỏ:

$ x='a%20%25%e3%81%82';printf "${x//\%/\\x}"
a %あ

Thêm --hoặc %bđể ngăn các đối số bắt đầu bằng dấu gạch ngang không được coi là tùy chọn.

Trong zsh ${x//%/a}thêm avào cuối nhưng ${x//\%/a}thay thế %bằng a.


1

Dưới đây là các bit có liên quan từ một tập lệnh khác (mà tôi vừa lấy trộm một cách đáng xấu hổ từ tập lệnh tải xuống youtube.com của tôi từ một câu trả lời khác) Tôi đã viết trước đây. Nó sử dụng sedvà vỏ để xây dựng một urldecode hoạt động.

set \! \" \# \$ \% \& \' \( \) \* \ \+ \, \/ \: \; \= \? \@ \[ \]
for c do set "$@" "'$c" "$c"; shift; done
curl -s "$url" | sed 's/\\u0026/\&/g;'"$(
    printf 's/%%%X/\\%s/g;' "$@"
)"

Tôi sẽ không thề rằng nó toàn diện - và thực tế tôi nghi ngờ điều đó - nhưng nó đã xử lý youtube đủ chắc chắn.


1

Đây là một hàm BASH để thực hiện chính xác điều đó:

function urldecode() {
        echo -ne $(echo -n "$1" | sed -E "s/%/\\\\x/g")
}

hoạt động như bùa mê
AbdElraouf Sabri

0

Một giải pháp khác sử dụng ruby ​​(câu trả lời trăn được chấp nhận không hiệu quả với tôi)

alias urldecode='ruby -e "require \"cgi\"; puts CGI.unescape(ARGV[0])"'
alias urlencode='ruby -e "require \"cgi\"; puts CGI.escape(ARGV[0])"'

Thí dụ

$ urldecode 'q+werty%3D%2F%3B'
q werty=/;

$ urlencode 'q werty=/;'
q+werty%3D%2F%3B
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.