2014-07-24 12 views
5

मुझे वेब पेज हेडर से 2 मान प्राप्त करने की आवश्यकता है जिसे मैं कर्ल का उपयोग कर रहा हूं। मैं व्यक्तिगत रूप से का उपयोग कर मूल्यों को प्राप्त करने में सक्षम है:बैश का उपयोग कर HTTP शीर्षलेखों का विश्लेषण कैसे करें?

response1=$(curl -I -s http://www.example.com | grep HTTP/1.1 | awk {'print $2'}) 
response2=$(curl -I -s http://www.example.com | grep Server: | awk {'print $2'}) 

लेकिन मैं समझ नहीं अलग तरह एक भी कर्ल अनुरोध का उपयोग कर मूल्यों grep के लिए कैसे:

response=$(curl -I -s http://www.example.com) 
http_status=$response | grep HTTP/1.1 | awk {'print $2'} 
server=$response | grep Server: | awk {'print $2'} 

हर प्रयास या तो एक त्रुटि की ओर जाता है संदेश या खाली मूल्य। मुझे यकीन है कि यह सिर्फ एक वाक्यविन्यास मुद्दा है।

+1

'$ प्रतिक्रिया | ... कर रहा है 'काम नहीं करेगा क्योंकि' $ प्रतिक्रिया' का मान कमांड नहीं है। 'echo $ प्रतिक्रिया' काम करना चाहिए। –

उत्तर

11

पूर्ण bash समाधान। प्रदर्शन कितनी आसानी से awk की आवश्यकता के बिना अन्य हेडर पार्स करने के लिए:

shopt -s extglob # Required to trim whitespace; see below 

while IFS=':' read key value; do 
    # trim whitespace in "value" 
    value=${value##+([[:space:]])}; value=${value%%+([[:space:]])} 

    case "$key" in 
     Server) SERVER="$value" 
       ;; 
     Content-Type) CT="$value" 
       ;; 
     HTTP*) read PROTO STATUS MSG <<< "$key{$value:+:$value}" 
       ;; 
    esac 
done < <(curl -sI http://www.google.com) 
echo $STATUS 
echo $SERVER 
echo $CT 

उत्पादन:

302 
GFE/2.0 
text/html; charset=UTF-8 

RFC-2616 के अनुसार, HTTP हेडर जो स्पष्ट रूप से खंड 3.1.2 में कहा गया है "Standard for the Format of ARPA Internet Text Messages" (RFC822) में वर्णित के रूप मॉडलिंग कर रहे हैं, :

फ़ील्ड-नाम प्रिंट से बना होना चाहिए सक्षम ASCII वर्ण (यानी, वर्ण जिनमें 33. और 126 के बीच मान हैं, कोलन को छोड़कर दशमलव)। सीआर या एलएफ को छोड़कर फील्ड-बॉडी किसी भी ASCII वर्णों से बना हो सकता है। (सीआर और/या वामो वास्तविक पाठ में मौजूद हो सकता है, वहीं वे की कार्रवाई क्षेत्र खुलासा द्वारा हटा दिया जाता है।)

तो ऊपर स्क्रिप्ट चाहिए पकड़ किसी भी RFC- [2] 822 के उल्लेखनीय अपवाद के साथ अनुपालन शीर्षलेख

+0

HTTP * केस दूसरों की तुलना में अलग क्यों है? मैं एक bash n00b हूँ, इसलिए अगर सवाल वास्तव में बुनियादी है तो कृपया मुझे माफ़ कर दो। – jpshook

+1

@ जेपीएसहूक 'आईएफएस =': '' का अर्थ है कि मैं ':' चरित्र के आधार पर इनपुट/मूल्य के रूप में इनपुट तोड़ता हूं। HTTP स्थिति रेखा में वह प्रारूप नहीं है। तो यह एक _special case_ है। –

+0

मुझे लगता है कि 'HTTP * 'केस को बेहतर प्रोटीओ स्टेटस एमएसजी <<<" $ key $ value "के रूप में बेहतर लिखा जा सकता है यदि संदेश में एक कोलन होता है (और' <<< 'का उपयोग करना, जो अवधारणात्मक रूप से है एक बच्चे को गूंजने के लिए सरल बनाने से सरल।) – rici

1

प्रक्रिया प्रतिस्थापन का उपयोग करना, (<(...)) आप खोल चर में पढ़ने में सक्षम हैं:

sh$ read STATUS SERVER < <(
     curl -sI http://www.google.com | 
     awk '/^HTTP/ { STATUS = $2 } 
      /^Server:/ { SERVER = $2 } 
      END { printf("%s %s\n",STATUS, SERVER) }' 
    ) 

sh$ echo $STATUS 
302 
sh$ $ echo $SERVER 
GFE/2.0 
+0

क्या होगा यदि 20 गुणों को पढ़ा जाए, तो क्या आप एक ही दृष्टिकोण का सुझाव देंगे? – jpshook

+0

@JPShook मेरे जैसा, मैं या तो 'awk' या' bash' का उपयोग करता हूं। ज्यादातर मामलों में, उनमें से _both का उपयोग करने के लिए यह बहुत कुछ नहीं जोड़ता है। लेकिन पर्याप्त पृष्ठभूमि के बिना, मैंने केवल अनुमान लगाया है कि आप एक संकर समाधान चाहते थे। –

+0

@JPShook मैंने एक अन्य उत्तर पोस्ट किया कि यह दर्शाता है कि आप अकेले 'बाश' का उपयोग कैसे कर सकते हैं। आपकी जरूरतों के आधार पर, यह एक बेहतर समाधान हो सकता है। –

1

यदि आप कुछ शीर्षकों से अधिक निकालना चाहते हैं, तो आप सभी शीर्षकों को एक बैश सहयोगी सरणी में रख सकते हैं। यहां एक सरल दिमाग वाला कार्य है जो मानता है कि कोई दिया गया शीर्षलेख केवल एक बार होता है। (Set-Cookie के लिए यह प्रयोग न करें, नीचे देखें।)

# Call this as: headers ARRAY URL 
headers() { 
    { 
    # (Re)define the specified variable as an associative array. 
    unset $1; 
    declare -gA $1; 
    local line rest 

    # Get the first line, assuming HTTP/1.0 or above. Note that these fields 
    # have Capitalized names. 
    IFS=$' \t\n\r' read $1[Proto] $1[Status] rest 
    # Drop the CR from the message, if there was one. 
    declare -gA $1[Message]="${rest%$'\r'}" 
    # Now read the rest of the headers. 
    while true; do 
     # Get rid of the trailing CR if there is one. 
     IFS=$'\r' read line rest; 
     # Stop when we hit an empty line 
     if [[ -z $line ]]; then break; fi 
     # Make sure it looks like a header 
     # This regex also strips leading and trailing spaces from the value 
     if [[ $line =~ ^([[:alnum:]_-]+):\ *((*[^ ]+)*)\ *$ ]]; then 
     # Force the header to lower case, since headers are case-insensitive, 
     # and store it into the array 
     declare -gA $1[${BASH_REMATCH[1],,}]="${BASH_REMATCH[2]}" 
     else 
     printf "Ignoring non-header line: %q\n" "$line" >> /dev/stderr 
     fi 
    done 
    } < <(curl -Is "$2") 
} 

उदाहरण:

$ headers so http://stackoverflow.com/ 
$ for h in ${!so[@]}; do printf "%s=%s\n" $h "${so[$h]}"; done | sort 
Message=OK 
Proto=HTTP/1.1 
Status=200 
cache-control=public, no-cache="Set-Cookie", max-age=43 
content-length=224904 
content-type=text/html; charset=utf-8 
date=Fri, 25 Jul 2014 17:35:16 GMT 
expires=Fri, 25 Jul 2014 17:36:00 GMT 
last-modified=Fri, 25 Jul 2014 17:35:00 GMT 
set-cookie=prov=205fd7f3-10d4-4197-b03a-252b60df7653; domain=.stackoverflow.com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly 
vary=* 
x-frame-options=SAMEORIGIN 

ध्यान दें कि ऐसा प्रतिक्रिया एक या अधिक कुकी, Set-Cookie हेडर में शामिल हैं, लेकिन हम केवल देख सकते हैं आखिरी एक क्योंकि बेवकूफ स्क्रिप्ट एक ही शीर्षलेख नाम के साथ प्रविष्टियों को ओवरराइट करता है। (जैसा कि होता है, केवल एक ही था लेकिन हम उसे नहीं जानते।) हालांकि स्क्रिप्ट को विशेष मामले Set-Cookie पर बढ़ाने के लिए संभव होगा, एक बेहतर दृष्टिकोण शायद कुकी-जार फ़ाइल प्रदान करना होगा, और -b का उपयोग करना होगा और इसे बनाए रखने के लिए -c कर्ल विकल्प।

संबंधित मुद्दे