2014-09-15 6 views
6

Szukam sposobu na wywołanie JEDNEJ curl i uzyskanie z niego zmiennych: jednego z nagłówkami i drugiego z treścią odpowiedzi.Uzyskaj zarówno nagłówki, jak i treść odpowiedzi na curl w dwóch oddzielnych zmiennych?

Znalazłem kilka pytań z pytaniem o sposób rozdzielania nagłówków od treści, ale ludzie wydają się być zainteresowani tylko jednym z nich. Potrzebuję zarówno nagłówków, jak i ciała.

Nie mogę użyć zewnętrznego pliku do przechowywania ciała (dlatego użycie opcji -o $ nie jest opcją).

mogę używać

headers=$(curl -D /dev/stdout $URL) 

uzyskać nagłówki do jednej zmiennej, ale w jaki sposób można przekierować wyjście do innej zmiennej?

Wielkie dzięki!

Odpowiedz

6
head=true 
while IFS= read -r line; do 
    if $head; then 
     if [[ -z $line ]]; then 
      head=false 
     else 
      headers+=("$line") 
     fi 
    else 
     body+=("$line") 
    fi 
done < <(curl -sD - "$url" | sed 's/\r$//') 
printf "%s\n" "${headers[@]}" 
echo === 
printf "%s\n" "${body[@]}" 

Aby dołączyć elementy tablicy w jedną zmienną skalarną:

the_body=$(IFS=$'\n'; echo "$body[*]") 

W bash 4.3, można używać nazwanych odniesień do uproszczenia przełączania z trybu „header” na „ciało "tryb:

declare -n section=headers 
while IFS= read -r line; do 
    if [[ $line = $'\r' ]]; then 
     declare -n section=body 
    fi 
    section+=("$line") 
done < <(curl -sD - "$url") 

Z jakiegoś powodu odpowiedź Glenna Jackmana nie dotarła do części ciała odpowiedzi. Musiałem oddzielić żądanie zwijania w inne rozszerzenie poleceń, a następnie zamknąć je w podwójnych cudzysłowach. Wtedy nie użyłem tablic, ale po prostu połączono wartości z zmiennymi. To działa dla mnie:

output=$(curl -si -d "" --request POST https://$url) 

head=true 
while read -r line; do 
    if $head; then 
     if [[ $line = $'\r' ]]; then 
     head=false 
    else 
     header="$header"$'\n'"$line" 
    fi 
    else 
     body="$body"$'\n'"$line" 
    fi 
done < <(echo "$output") 

Dziękuję, Glenn!

+0

Starałem się, aby coś takiego działało, ale nie rozumiem, dlaczego "kot" nie czyta dalej od miejsca, w którym "sed" zostało przerwane: '{h = $ (sed '/^$/q '); b = $ (cat); } <<(curl -si $ url) ' – ooga

+0

To dobre pytanie. Pamiętaj, że curl zwraca nagłówki z końcówkami wiersza '\ r \ n', więc'/^ $/'nie będzie oznaczać końca nagłówków, będziesz musiał użyć'/^ \ r $/'lub rozbierz powroty karetki, tak jak ja w mojej odpowiedzi. Ale nawet poprawiam to, nie wiem, dlaczego sed zjada wszystkie dane wejściowe po tym, jak powinien przestać. –

+1

Chociaż 'sed' przetwarza swoje wejście tylko jedną linię na raz, to nie znaczy, że * czyta * tylko jedną linię na raz ze standardowego wejścia. Może odczytywać linie 'N', a inne' N-1' są buforowane, dopóki 'sed' nie zostanie wykonane pierwszym wierszem. Jeśli 'sed' wyjdzie przed przetworzeniem reszty bufora, wiersze te nie zostaną" przywrócone "do standardowego wejścia dla następnego polecenia (w tym przypadku' cat') do konsumpcji. – chepner

6

Chciałbym udostępnić sposób analizowania odpowiedzi curl bez żadnego zewnętrznego programu, tylko bash.

Po pierwsze, uzyskaj odpowiedź żądania zwijania, przekazując -sw "%{http_code}".

res=$(curl -sw "%{http_code}" $url) 

Wynikiem będzie ciąg zawierający treść, a następnie kod http.

Następnie uzyskać kod http:

http_code="${res:${#res}-3}" 

i ciało:

if [ ${#res} -eq 3 ]; then 
    body="" 
else 
    body="${res:0:${#res}-3}" 
fi 

pamiętać, że jeśli długość HTTP_CODE i odpowiedzi są równe (długość 3), ciało jest pusty. Inaczej, po prostu usuń kod http, a otrzymasz ciało.

+1

To jest prostszy sposób sprawdzenia tylko kodu status_code. Jednak oryginalne pytanie dotyczyło parsowania pól nagłówka, podoba mi się to rozwiązanie i wykorzystałem je w mojej bibliotece. (https://bitbucket.org/kisp/bash_lib/src/ccd542aa361bf66458195d71a93aeb475100c832/http_get.sh?fileviewer=file-view-default) dzięki za napiwek. – kisp

+0

@kisp Cieszę się, że go używasz. Należy pamiętać, że nie przetestowałem go bardzo, chociaż powinien działać dobrze, ponieważ jest bardzo prosty. – 0x10203040

+0

Wiem, że nie jest to ściśle odpowiedź na pytanie, ale jest ono bardzo użyteczne (i wystarczająco zbliżone, aby zostać wznowione). –

Powiązane problemy