Hier ist die reine BASH-Antwort.
Update : Da viele Änderungen diskutiert wurden, habe ich dies auf https://github.com/sfinktah/bash/blob/master/rawurlencode.inc.sh gegen die niemand eine PR herausgeben kann.
Hinweis : Diese Lösung ist nicht dafür gedacht, Unicode- oder Multi-Byte-Zeichen zu kodieren - diese liegen außerhalb der bescheidenen Möglichkeiten von BASH einheimische Fähigkeiten. Es ist nur dazu gedacht, Symbole zu kodieren, die sonst die Argumentübergabe in POST- oder GET-Anfragen ruinieren würden, z. B. '&', '=' und so weiter.
Sehr wichtiger Hinweis : VERSUCHEN SIE NICHT, IHRE EIGENE UNICODE-KONVERTIERUNGSFUNKTION ZU SCHREIBEN, IN KEINER SPRACHE, NIEMALS. Siehe Ende der Antwort.
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
}
Sie können es auf zwei Arten verwenden:
easier: echo http://url/q?=$( rawurlencode "$args" )
faster: rawurlencode "$args"; echo http://url/q?${REPLY}
[bearbeitet]
Hier ist die passende Funktion rawurldecode(), die - bei aller Bescheidenheit - großartig ist.
# 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
}
Mit dem Matching-Set können wir nun einige einfache Tests durchführen:
$ diff rawurlencode.inc.sh \
<( rawurldecode "$( rawurlencode "$( cat rawurlencode.inc.sh )" )" ) \
&& echo Matched
Output: Matched
Und wenn Sie wirklich das Gefühl haben, dass Sie ein externes Tool brauchen (nun ja, es geht viel schneller und kann auch Binärdateien und dergleichen...), habe ich dies auf meinem OpenWRT-Router gefunden...
replace_value=$(echo $replace_value | sed -f /usr/lib/ddns/url_escape.sed)
Dabei war url_escape.sed eine Datei, die diese Regeln enthielt:
# 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
Es ist zwar nicht unmöglich, ein solches Skript in BASH zu schreiben (wahrscheinlich mit xxd
und ein sehr umfangreicher Regelsatz), die UTF-8-Eingaben verarbeiten können, gibt es schnellere und zuverlässigere Methoden. Der Versuch, UTF-8 in UTF-32 zu dekodieren, ist eine nicht-triviale Aufgabe, die mit Genauigkeit zu erledigen ist, obwohl es sehr einfach ist, sie ungenau zu erledigen, so dass man denkt, es funktioniert, bis zu dem Tag, an dem es nicht mehr funktioniert.
Selbst das Unicode-Konsortium hat seinen Beispielcode entfernt, nachdem es festgestellt hatte, dass er nicht mehr zu 100 % mit dem aktuellen Standard kompatibel war.
Der Unicode-Standard wird ständig weiterentwickelt und ist sehr differenziert geworden. Jede Implementierung, die Sie zusammenbasteln können, wird nicht richtig konform sein, und selbst wenn Sie es mit extremem Aufwand schaffen, würde es bleiben willfährig.