Próbuję napisać skrypt bash do testowania, który pobiera parametr i wysyła go przez curl do strony internetowej. Muszę zakodować adres URL, aby upewnić się, że znaki specjalne są poprawnie przetwarzane. 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 $@
Odpowiedzi:
Użyj
curl --data-urlencode
; zman curl
:Przykładowe użycie:
Zobacz stronę manuala aby uzyskać więcej informacji.
Wymaga to curl 7.18.0 lub nowszego (wydanego w styczniu 2008) . Posługiwać się
curl -V
aby sprawdzić, którą wersję posiadasz.Możesz również zakodować ciąg zapytania :
źródło
curl -G --data-urlencode "blah=df ssdf sdf" --data-urlencode "blah2=dfsdf sdfsd " http://whatever.com/whatever
curl --data-urlencode "description=![image]($url)" www.example.com
. Masz pomysł, dlaczego? `"
the‽Oto czysta odpowiedź BASH.
Możesz użyć go na dwa sposoby:
[edytowany]
Oto pasująca funkcja rawurldecode (), która - przy całej skromności - jest niesamowita.
Dzięki pasującemu zestawowi możemy teraz wykonać kilka prostych testów:
A jeśli naprawdę czujesz, że potrzebujesz zewnętrznego narzędzia (cóż, będzie działać znacznie szybciej i może tworzyć pliki binarne itp.) Znalazłem to na moim routerze OpenWRT ...
Gdzie url_escape.sed był plikiem zawierającym następujące reguły:
źródło
Jogging «à l'Hèze»
Generuje ciąg,Jogging%20%abà%20l%27Hèze%bb
który nie może być przesłany do JSdecodeURIComponent
:(\u0144
), naiwnie wyświetli% 144, ╡ (\u2561
) zostanie wyprowadzony jako% 2561. Prawidłowe odpowiedzi dla tych kodów będą odpowiednio% C5% 84% 0A i% E2% 95% A1.Użyj
URI::Escape
modułu iuri_escape
funkcji Perla w drugiej linii skryptu bash:Edycja: Napraw problemy z cytowaniem, jak sugerował Chris Johnsen w komentarzach. Dzięki!
źródło
echo
, potok i<>
), a teraz działa nawet wtedy, gdy 2 $ zawiera apostrof lub podwójne cudzysłowy. Dzięki!echo
również:value="$(perl -MURI::Escape -e 'print uri_escape($ARGV[0]);' "$2")"
Inną opcją jest użycie
jq
(jako filtru):-R
(--raw-input
) traktuje wiersze wejściowe jako ciągi zamiast analizować je jako JSON, a-sR
(--slurp --raw-input
) odczytuje dane wejściowe w jednym ciągu.-r
(--raw-output
) wyświetla zawartość ciągów zamiast literałów ciągów JSON.Jeśli dane wejściowe nie są danymi wyjściowymi innego polecenia, możesz je zapisać w
jq
zmiennej łańcuchowej:-n
(--null-input
) nie odczytuje danych wejściowych i--arg name value
zapisujevalue
w zmiennejname
jako ciąg znaków. W filtrze$name
(w pojedynczych cudzysłowach, aby uniknąć rozwinięcia przez powłokę), odwołuje się do zmiennejname
.Opakowany jako funkcja Bash, staje się:
Lub ten procent koduje wszystkie bajty:
źródło
curl
żeby zakodować to działa, a jeśli bash ma wbudowane, które byłoby akceptowalne - alejq
wydaje się, że jest to właściwe dopasowanie, ale jestem daleki od osiągnięcia poziomu komfortu z to narzędzie)@uri
nie jest jakąś zmienną, ale dosłowny filtr jq używany do formatowania ciągów znaków i zmiany znaczenia; szczegóły w instrukcji jq (przepraszam, brak bezpośredniego linku, trzeba szukać@uri
na stronie ...)printf "http://localhost:8082/" | jq -sRr '@uri'
ze względu na kompletność, wiele rozwiązań wykorzystujących
sed
lubawk
tłumaczących specjalny zestaw znaków, a zatem jest dość dużych pod względem rozmiaru kodu, a także nie tłumaczy innych znaków specjalnych, które powinny być zakodowane.bezpiecznym sposobem na urlencode byłoby po prostu zakodowanie każdego bajtu - nawet tych, które byłyby dozwolone.
xxd dba o to, aby dane wejściowe były traktowane jako bajty, a nie znaki.
edytować:
xxd jest dostarczany z pakietem vim-common w Debianie, a ja byłem na systemie, w którym nie został zainstalowany i nie chciałem go instalować. Altornatywą jest użycie
hexdump
z pakietu bsdmainutils w Debianie. Zgodnie z poniższym wykresem prawdopodobieństwo zainstalowania bsdmainutils i vim-common powinno być prawie równe:http://qa.debian.org/popcon-png.php?packages=vim-common%2Cbsdmainutils&show_installed=1&want_legend=1&want_ticks=1
ale tutaj jest wersja, która używa
hexdump
zamiastxxd
i pozwala uniknąćtr
połączenia:źródło
xxd -plain
powinno zdarzyć się POtr -d '\n'
!\n
znaki zostaną przetłumaczonexxd -plain
na0a
. Nie wierz mi na słowo, spróbuj sam:echo -n -e '\n' | xxd -plain
to dowodzi, że twójtr -d '\n'
jest tutaj bezużyteczny, ponieważ nie może być żadnego\n
poxxd -plain
Second,echo foobar
dodaje swój własny\n
znak na końcu łańcucha znaków, więcxxd -plain
nie jest karmionyfoobar
zgodnie z oczekiwaniami, ale zfoobar\n
. następniexxd -plain
tłumaczy go na ciąg znaków, który kończy się na0a
, co czyni go nieodpowiednim dla użytkownika. Można dodać-n
doecho
jego rozwiązania.xxd
połączenie należy przedtr -d
połączeniem. Należy tam, aby każda nowa liniafoobar
została przetłumaczona przezxxd
.tr -d
Poxxd
wywołaniu jest usunięcie newlines że xxd produkuje. Wygląda na to, że nigdy nie masz foobara wystarczająco długiego, abyxxd
produkować nowe linie, ale przy długich wejściach tak będzie. Więc totr -d
jest konieczne. W przeciwieństwie do twojego założeniatr -d
NIE było usuwania nowych linii z danych wejściowych, ale z danychxxd
wyjściowych. Chcę zachować nowe wiersze na wejściu. Twoim jedynym słusznym punktem jest to, że echo dodaje niepotrzebną nową linię.echo -n
czego tak naprawdę brakowałoJeden z wariantów może być brzydki, ale prosty:
Oto na przykład wersja jednoliniowa (zgodnie z sugestią Bruno ):
źródło
date
polecenia…date | curl -Gso /dev/null -w %{url_effective} --data-urlencode @- "" | cut -c 3-
(Musiszcut
wyłączyć pierwsze 2 znaki, ponieważ wyjście curl jest technicznie względnym adresem URL z ciągiem zapytania.)%0A
na końcu, użyjprintf
zamiastecho
.Uważam, że jest bardziej czytelny w Pythonie:
potrójny „gwarantuje, że pojedyncze cytaty wartości nie zaszkodzą. urllib znajduje się w standardowej bibliotece. To działa na przykład dla tego zwariowanego (prawdziwego świata) adresu URL:
źródło
encoded_value=$(python3 -c "import urllib.parse; print (urllib.parse.quote('''$value'''))")
.python -c 'import urllib, sys; sys.stdout.writelines(urllib.quote_plus(l, safe="/\n") for l in sys.stdin)'
prawie nie ma problemów z cytowaniem i powinien być efektywny pod względem pamięci / prędkości (nie sprawdzono, z wyjątkiemsys.argv
zamiast zastępować$value
go łańcuchem analizowanym później jako kod. Co jeślivalue
zawarte''' + __import__("os").system("rm -rf ~") + '''
?python -c "import urllib;print urllib.quote(raw_input())" <<< "$data"
Uważam, że następujący fragment kodu jest przydatny do umieszczenia go w łańcuchu wywołań programu, w których URI :: Escape może nie być zainstalowany:
( źródło )
źródło
perl -pe 's/\%(\w\w)/chr hex $1/ge'
(źródło: unix.stackexchange.com/questions/159253/... )perl -pe 's/(\W)/sprintf("%%%02X", ord($1))/ge'
co pozwala na litery, cyfry i podkreślenia, ale koduje wszystko inne.Jeśli chcesz uruchomić
GET
żądanie i użyć czystego curl, po prostu dodaj--get
do rozwiązania @ Jacob.Oto przykład:
źródło
Bezpośredni link do wersji awk: http://www.shelldorado.com/scripts/cmds/urlencode
Używałem go od lat i działa jak urok
źródło
To może być najlepszy:
źródło
after=$(echo -e ...
od
Polecenie nie jest powszechne.od
ponieważ używa innego formatu wyjściowego niż GNUod
. Na przykładprintf aa|od -An -tx1 -v|tr \ -
drukuje-----------61--61--------------------------------------------------------
w systemie OS Xod
i-61-61
GNUod
. Możesz używaćod -An -tx1 -v|sed 's/ */ /g;s/ *$//'|tr \ %|tr -d \\n
z OS Xod
lub GNUod
.xxd -p|sed 's/../%&/g'|tr -d \\n
robi to samo, mimo żexxd
nie ma go w POSIX, aleod
jest.Oto rozwiązanie Bash, które nie wywołuje żadnych programów zewnętrznych:
źródło
á
spowoduje to zakodowanie ciągu wewnątrz $ 1 i wyprowadzenie go w $ url. chociaż nie musisz umieszczać go w var, jeśli chcesz. BTW nie uwzględnił sed dla tabu, sądząc, że zamieni go w spacje
źródło
Za pomocą php ze skryptu powłoki:
źródło
Dla tych z Was, którzy szukają rozwiązania, które nie potrzebuje perla, oto takie, które potrzebuje tylko hexdump i awk:
Połączone ze sobą z kilku miejsc w sieci i trochę lokalnych prób i błędów. Działa świetnie!
źródło
uni2ascii jest bardzo przydatny:
źródło
%
i przestrzeń (ta ostatnia może być usunięta z-s
flagą)Jeśli nie chcesz polegać na Perlu, możesz także użyć sed. To trochę bałagan, ponieważ każda postać musi być uciekana indywidualnie. Utwórz plik o następującej treści i wywołaj go
urlencode.sed
Aby go użyć, wykonaj następujące czynności.
Spowoduje to podzielenie łańcucha na część, która wymaga kodowania, a część, która jest w porządku, koduje część, która jej potrzebuje, a następnie ponownie łączy.
Możesz to dla wygody umieścić w skrypcie sh, może wymagać kodowania parametru, umieścić go na swojej ścieżce, a następnie możesz po prostu wywołać:
źródło
źródło
Możesz emulować javascript
encodeURIComponent
w perlu. Oto polecenie:Możesz ustawić to jako alias bash w
.bash_profile
:Teraz możesz przesyłać do
encodeURIComponent
:źródło
Oto wersja węzła:
źródło
node
całkowicie uniknąć . Opublikowałem rozwiązanie tylko dla Bash. :)node -p 'encodeURIComponent(require("fs").readFileSync(0))'
Pytanie dotyczy robienia tego w bashu i nie ma potrzeby używania Pythona lub Perla, ponieważ w rzeczywistości istnieje jedno polecenie, które robi dokładnie to, co chcesz - „urlencode”.
Jest to również znacznie lepsze, ponieważ powyższy perl na przykład nie koduje poprawnie wszystkich znaków. Wypróbuj to, używając długiej kreski, którą otrzymujesz z Worda, a otrzymasz nieprawidłowe kodowanie.
Uwaga: aby udostępnić to polecenie, musisz zainstalować „klientów gridsite-klientów”.
źródło
urlencode
. Jakiej wersji używasz?Prosta opcja PHP:
źródło
Ruby, dla kompletności
źródło
Inne podejście php:
źródło
echo
doda znak nowej linii (hex0xa
). Aby temu zapobiec, użyjecho -n
.Oto moja wersja dla jesshell busy dla systemu wbudowanego, pierwotnie przyjąłem wariant Orwellophile:
źródło
Oto funkcja POSIX, aby to zrobić:
Przykład:
Źródło
źródło
Oto konwersja jednowierszowa przy użyciu Lua, podobna do odpowiedzi blueyed, z wyjątkiem wszystkich niezarezerwowanych znaków RFC 3986 niezakodowanych (jak ta odpowiedź ):
Ponadto może być konieczne upewnienie się, że znaki nowego wiersza w ciągu są konwertowane z LF na CRLF, w którym to przypadku można wstawić
gsub("\r?\n", "\r\n")
łańcuch przed kodowaniem procentowym.Oto wariant, który w niestandardowym stylu application / x-www-form-urlencoded wykonuje normalizację nowej linii, a także koduje spacje jako „+” zamiast „% 20” (które prawdopodobnie można by dodać do Fragment kodu Perla przy użyciu podobnej techniki).
źródło
Po zainstalowaniu php używam w ten sposób:
źródło
To jest wersja ksh odpowiedzi orwellophile zawierającej funkcje rawurlencode i rawurldecode (link: Jak urlencode dane dla polecenia curl? ). Nie mam wystarczającej liczby przedstawicieli, aby opublikować komentarz, stąd nowy post ..
źródło
Co lepiej parsowałoby adresy URL niż javascript?
źródło
node -p 'encodeURIComponent(require("fs").readFileSync(0))'
echo | ...
jest zły, aecho -n | ...
pomija znak nowej linii.Poniższe informacje oparte są na odpowiedzi Orwellophila, ale rozwiązują wielobajtowy błąd wymieniony w komentarzach, ustawiając LC_ALL = C (lewę z vte.sh). Napisałem to w formie funkcji odpowiedniej PROMPT_COMMAND, ponieważ właśnie tak go używam.
źródło