Prozentcodierung einer Zeichenfolge

13

Einführung

Wie einige von Ihnen vielleicht wissen, enthalten URLs tatsächlich eine Liste von Zeichen, die bestimmte Aufgaben ausführen. Zum Beispiel kann die /trennt Charakter Teile der URL, und die ?, &und =werden Zeichen verwendet , um Abfrageparameter an den Server übergeben. In der Tat gibt es eine Reihe von Zeichen mit Sonderfunktionen: $&+,/:;=?@. Wenn Sie diese Zeichen in der URL aus einem anderen Grund als den Sonderfunktionen verwenden müssen, müssen Sie eine sogenannte Prozentcodierung durchführen .

Prozentcodierung ist, wenn Sie den Hexadezimalwert eines Zeichens nehmen und ein %Zeichen an den Anfang des Zeichens stellen. Beispielsweise ?würde das Zeichen wie folgt codiert %3Fund das Zeichen &würde wie folgt codiert %26. In einer URL können Sie diese Zeichen als Daten über die URL senden, ohne dass Analyseprobleme auftreten. Ihre Herausforderung besteht darin, eine Zeichenfolge zu verwenden und alle Zeichen, die codiert werden müssen, in Prozent zu codieren.

Die Herausforderung

Sie müssen ein Programm oder eine Funktion schreiben, die eine einzelne Zeichenfolge enthält, die aus Zeichen mit den Codepunkten 00-FF (ASCII- und Extended ASCII-Zeichen) besteht. Sie müssen dann bei Bedarf für jedes Zeichen die gleiche Zeichenfolge in Prozent ausgeben oder zurückgeben. Built-Ins, die diese Aufgabe erfüllen, sind nicht zulässig, und es handelt sich auch nicht um Standardlücken. Als Referenz finden Sie hier eine Liste aller Zeichen, die in Prozent codiert werden müssen:

  • Steuerzeichen (Codepunkte 00-1F und 7F)
  • Erweiterte ASCII-Zeichen (Codepoints 80-FF)
  • Reservierte Zeichen ( $&+,/:;=?@dh Codepunkte 24, 26, 2B, 2C, 2F, 3A, 3B, 3D, 3F, 40)
  • Unsichere Zeichen ( " <>#%{}|\^~[]`dh Codepunkte 20, 22, 3C, 3E, 23, 25, 7B, 7D, 7C, 5C, 5E, 7E, 5B, 5D, 60)

Hier ist die gleiche Liste, aber stattdessen als Liste der Dezimalcodepunkte:

0-31, 32, 34, 35, 36, 37, 38, 43, 44, 47, 58, 59, 60, 62, 61, 63, 64, 91, 92, 93, 94, 96, 123, 124, 125, 126, 127, 128-255

Dies ist Codegolf, also gewinnt der kürzeste Code in Bytes (oder die genehmigte alternative Bewertungsmethode)!

Testfälle

http://codegolf.stackexchange.com/  =>  http%3A%2F%2Fcodegolf.stackexchange.com%2F
[@=>]{#}  =>  %5B%40%3D%3E%5D%7B%23%7D
Test String  =>  Test%20String
ÑÉÐÔ®  =>  %D1%C9%D0%D4%AE
  =>  %0F%16%7F (Control characters 0F, 16, and 7F)
 ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ  =>  %80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF (Extended ASCII characters 80-FF)
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  =>  %20!%22%23%24%25%26'()*%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E
GamrCorps
quelle
Hätten Sie einen Testfall, der die Steuerzeichen zeigt?
Undichte Nonne
@LeakyNun erledigt.
GamrCorps
Ich bin sicher, Codepoint EFenthält kein Fragezeichen.
User48538
@ zyabin101 wo hast du das gefunden? Ich sehe es nicht.
GamrCorps
"Zum Beispiel würde das Zeichen? Als% EF ... codiert werden"
user48538

Antworten:

2

Pyth, 30 28 26 Bytes

L?hx+G+rG1CGbb+\%.HCbsmydz

versuche es online

Erläuterung

L?hx+G+rG1CGbb+\%.HCbsmydz
L?hx+G+rG1CGbb+\%.HCb       First part, L defines the function y(b)
 ?hx+G+rG1CGbb+\%.HCb       ? is the ternary operator
  hx+G+rG1CGb               This part will be evaluated
  hx                        x will find the first occurence of a
                            character in a list. If it doesn't
                            find one, it will return -1. hx then
                            equals 0 (or false).
    +G+rG1CG                The list of allowed characters, a
                            concetanation (+) of the alphabet (G),
                            uppercase alphabet (rG1) and numbers
                            (CG, see below for details)
            b               The character to find in the list
             b              True branch of the ternary operator,
                            the character is allowed and returned.
              +\%.HCb       False branch, convert to hex and add %
                     smydz  The actual program
                      mydz  Map every character in the input (z)
                            using the function y on every d
                     s      Join the array, and implicit print.

CGist dieser Trick , der eine riesige Zahl generiert, die alle möglichen Ziffern enthält. Dies ist perfekt, da Duplikate nicht berücksichtigt werden, wenn geprüft wird, ob sich eine Zeichenfolge in einer anderen befindet.

Lars
quelle
Diese Antwort entspricht nicht der Spezifikation in der Frage. Es gibt mehr erlaubte Zeichen als nur A-Za-z0-9. Beispielsweise .sollte beibehalten werden, anstatt übersetzt zu werden %2E. (cc: @GamrCorps)
DLosc
3

Vim, 67 Bytes / Tastenanschläge

:s/\c[^a-z!'()*0-9._-]/\='%'.printf("%02x",char2nr(submatch(0)))/g<cr>

Beachten Sie, dass dies <cr>die Eingabetaste darstellt, z. B. 0x0Dein einzelnes Byte.

Dies ist eine ziemlich einfache Lösung. Erläuterung:

:s/                                                                    "Search and replace
   \c                                                                  "Case-insensitive
     [^a-z!'()*0-9._-]/                                                "A negative range. Matches any character not alphabetc, numeric or in "!'()*0-9._-"
                       \=                                              "Evaluate
                         '%'                                           "a percent sign string
                            .                                          "Concatenated with
                             printf("%02x",char2nr(submatch(0)))       "The hex value of the character we just matched
                                                                /g     "Make this apply to ever match
                                                                  <cr> "Actually run the command

Dieser printf("%02x",char2nr(submatch(0)))Müll ist schrecklich ungolfisch .

DJMcMayhem
quelle
"Dieser printf("%02x",char2nr(submatch(0)))Müll ist schrecklich ungolfig" und extrem hacky
Leaky Nun
2

Perl, 40 Bytes

39 Byte Code + -p.

Ein bisschen lahm, aber ich denke, es ist die kürzeste Lösung ...

s/[^!'()*-.\w]/sprintf'%%%02x',ord$&/ge

Verwendung

echo -n ' !"#$%&'\''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqstuvwxyz{|}~' | perl -pe "s/[^'()*-.\w]/sprintf'%%%02x',ord$&/ge"
%20%21%22%23%24%25%26'()*+,-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqstuvwxyz%7b%7c%7d%7e
Dom Hastings
quelle
2

Julia, 47 Bytes

!s=replace(s,r"[^\w!'()*.-]",c->"%"hex(c[1],2))

Probieren Sie es online!

Dennis
quelle
1

Python 3, 92 Bytes

5 bytes dank orlp.

1 Byte dank Sp3000.

import re;lambda s:''.join(re.match("[!'-*.0-9\w-]",c,256)and c or'%%%02X'%ord(c)for c in s)

Ideone es!

Undichte Nonne
quelle
re.match("[!'()*.0-9A-Za-z_-]",c)and c or'%%%02X'%ord(c)
Orlp
@ Sp3000 \wenthält erweiterte ASCII
Leaky Nun
Also, '()*->'-*
Sp3000
Ich denke \wfunktioniert mit der 256( re.ASCII) Option: ideone . Es funktioniert definitiv in Python 3 auf ideone und das auch sollte mit u"..."Strings in Python 2 funktionieren, aber Ideone scheint irre Dinge mit letzterem zu machen (z. B. print len(u"ÑÉÐÔ®")gibt 10 auf Ideone , 5 auf repl.it und meinem Computer, obwohl alles 2.7 ist. 10)
Sp3000
1

C 83 Bytes

f(char*p){for(;*p;++p)printf(isalnum(*p)||strchr("!'()*-._",*p)?"%c":"%%%02X",*p);}
orlp
quelle
1

Python, 86 Bytes

lambda s:"".join(["%%%02X"%ord(c),c][c<"{"and c.isalnum()or c in"!'()*-._"]for c in s)

Port meiner C-Antwort.

orlp
quelle
1

Ruby, 37 + 3 = 40 Bytes

Führen Sie mit -p(3 zusätzliche Bytes) wie folgt aus $ ruby -p percent_encode.rb:

gsub(/[^\w!'()*-.]/){"%%%02X"%$&.ord}
daniero
quelle
1

Jelly , 28 27 Bytes

ḟØWḟ©“!'()*-.”Od⁴‘ịØH”%p®,y

Dies ist eine monadische Verbindung. Probieren Sie es online!

Wie es funktioniert

ḟØWḟ©“!'()*-.”Od⁴‘ịØH”%p®,y  Monadic link. Argument: s (string)

 ØW                          Yield “0...9A...Z_a...z”.
ḟ                            Remove these characters from s.
     “!'()*-.”               Yield “!'()*-.”.
   ḟ                         Remove these characters from s.
    ©                        Copy the result to the register.
              O              Ordinal; get the code point of each character.
               d⁴            Divmod 16; yield quotient and remainder modulo 16.
                 ’           Decrement the results.
                  ịØH        Index into “0123456789ABCDEF”.
                     ”p%     Perform Cartesian product with ”%, prepending it to
                             each pair of hexadecimal digits.
                        ®,   Yield [t, r], where t is the string in the register
                             and r the result of the Cartesian product.
                          y  Use this pair to perform transliteration on s.
Dennis
quelle
1

Haskell, 201 179 178 127 119 Bytes

import Data.Char;import Numeric;f=(=<<)(\c->if isAlphaNum c&&isAscii c||elem c"-_.~"then[c]else '%':(showHex$ord c)"")

Ungolfed:

import Data.Char
import Numeric

f=(=<<) e
e c = if isAlphaNum c && isAscii c && c `elem` "-_.~" then [c] else '%' : (showHex $ ord c) ""
sham1
quelle
Können Sie einige Leerzeichen entfernen?
14.
Sie können das verlieren where, das ifin Wachen verwandeln , es partiell machen, das letzte Argument von showHex, Inline p, Inline s, die Signatur verlieren, das neu anordnen elemund noch mehr Leerzeichen verlieren. In erster Näherung bin ich auf diese Weise auf 118 gekommen.
MarLinn
Vielen Dank an @MarLinn für ein paar gute Vorschläge zum Verkleinern des Codes. Ich hatte jedoch einige Probleme mit bestimmten Vorschlägen. Erstens, wenn ich die Unterschrift entferne, wird sich GHC darüber beschweren No instance for (Foldable t0) arising from a use of ‘foldr’. Es besagt, dass der Typ der Funktion nicht eindeutig ist, was zu einer gefolgerten Bindung von führt f :: t0 Char -> [Char]. Und zweitens konnte ich das leere Zeichenfolgenargument nicht aus showHex entfernen, da es ein ShowS zurückgibt, das ein Typ-Alias ​​ist, um String -> Stringdie leere Zeichenfolge zu benötigen.
Sham1
@ sham1, ja, ShowSbraucht einen String ... aber du hast einen: den, den du hinzufügst (++). So können Sie beide gleichzeitig verlieren. Das ShowSsieht eigentlich so aus. Ich bekomme keinen Tippfehler, also ist es wohl eine Versionssache? Zwei andere Dinge, die mir mittlerweile aufgefallen sind:otherwise Kann immer durch 1<2(eine Abkürzung für True) ersetzt werden, aber wenn Sie zu zurückkehren, ifkönnen Sie ealle Namen inline setzen und löschen. Und sogar die Falte in ein concatMap, dh ein (>>=). Spart nicht viel, aber wenigstens ein bisschen. Könnte auch den Tippfehler beheben.
MarLinn
0

Python 2, 78 Bytes

lambda s:"".join(["%%%02x"%ord(c),c][c.isalnum()or c in"!'()*-._"]for c in s)

Schöner formatiert:

lambda s:
    "".join(["%%%02x" % ord(c), c][c.isalnum() or c in"!'()*-._"] for c in s)
Byte Commander
quelle
0

SQF , 199 176

Verwenden des Formats "Funktion als Datei":

i="";a="0123456789ABCDEF!'()*-.GHIJKLMNOPQRSTUVWXYZ_";{i=i+if((toUpper _x)in a)then{_x}else{x=(toArray[_x])select 0;"%"+(a select floor(x/16))+(a select(x%16))}}forEach _this;i

Anrufen als "STRING" call NAME_OF_COMPILED_FUNCTION

Οurous
quelle
0

PowerShell v2 +, 146 Byte

param($n)37,38+0..36+43,44,47+58..64+91,93+96+123..255-ne33|%{$n=$n-replace"[$([char]$_)]",("%{0:x2}"-f$_)};$n-replace'\\','%5c'-replace'\^','%5e'

Lange, weil ich einen anderen Ansatz zeigen wollte, als nur die gleiche Regex-Zeichenfolge einzufügen, die alle anderen verwenden.

Statt hier, wir Schleife durch jeden Code Punkt, muss Prozent-codiert sein, und ein wörtliche tun -replaceauf der Eingabezeichenfolge $njede Iteration (re sparend wieder in $n). Dann müssen wir die zwei Sonderzeichen berücksichtigen, die maskiert werden müssen, \und ^diese befinden sich -replaceam Ende in separaten Elementen. Da wir den letzten String nicht erneut gespeichert haben, verbleibt er in der Pipeline und das Drucken ist implizit.

AdmBorkBork
quelle
0

16/32-Bit x86-Assembly, 73 Byte

Byte-Code:

AC 3C 21 72 2A 74 3E 3C 26 76 24 3C 2B 72 36 3C
2C 76 1C 3C 2F 72 2E 74 16 3C 3A 72 28 74 10 3C
5F 74 22 50 0C 60 3C 60 74 02 3C 7B 58 72 16 D4
10 3C 09 1C 69 2F 86 E0 3C 09 1C 69 2F 92 B0 25
AA 92 AA 86 E0 AA E2 B8 C3

Demontage:

l0: lodsb         ;fetch a character
    cmp  al, 21h
    jb   l1       ;encode 0x00-0x20
    je   l2       ;store 0x21
    cmp  al, 26h
    jbe  l1       ;encode 0x22-0x26
    cmp  al, 2bh
    jb   l2       ;store 0x27-0x2A
    cmp  al, 2ch
    jbe  l1       ;encode 0x2B-0x2C
    cmp  al, 2fh
    jb   l2       ;store 0x2D-0x2E
    je   l1       ;encode 0x2F
    cmp  al, 3ah
    jb   l2       ;store 0x30-0x39
    je   l1       ;encode 0x3A
    cmp  al, 5fh
    je   l2       ;store 0x5F
    push eax
    or   al, 60h  ;merge ranges
    cmp  al, 60h
    je   l3       ;encode 0x40, 0x60
    cmp  al, 7bh
l3: pop  eax
    jb   l2       ;store 0x41-0x5A, 0x61-0x7A
                  ;encode 0x3B-0x3F, 0x5B-0x5E, 0x7B-0xFF

l1: aam  10h      ;split byte to nibbles
    cmp  al, 9    ;convert 0x0A-0x0F 
    sbb  al, 69h  ;to
    das           ;0x41-0x46 ('A'-'F')
    xchg ah, al   ;swap nibbles
    cmp  al, 9    ;do
    sbb  al, 69h  ;other
    das           ;half
    xchg edx, eax ;save in edx
    mov  al, '%'
    stosb         ;emit '%'
    xchg edx, eax
    stosb         ;emit high nibble
    xchg ah, al

l2: stosb         ;emit low nibble or original character
    loop l0       ;until end of string
    ret

Aufruf mit:
- esi = Zeiger auf Puffer, der den Quelltext enthält;
- edi = Zeiger auf den Puffer, der den codierten String empfängt;
- ecx = Länge der Quellzeichenfolge.

Peter Ferrie
quelle