दिलचस्प पोस्ट
जावा में किसी भी वेब पेज से छवि को कैसे डाउनलोड करें मैं फाइलों को जार फ़ाइल के अंदर कैसे सूचीबद्ध करूं? एफओपीन नापसंद चेतावनी क्या रिक्त या रिक्त संग्रह वापस करना बेहतर है? मैं अपाचे टॉमकैट में चल रहे वेबएप के लिए मेनिफेस्ट फाइल कैसे पढ़ूं? फ़ंक्शन तर्क के रूप में jQuery डॉलर का चिह्न ($)? XML तत्व में कोई विशेषता मान प्राप्त करना पीपीपी में इनपुट और आउटपुट की सफाई का पवित्र कंसा? डायरेक्ट कास्टिंग बनाम 'एसे' ऑपरेटर? Promise.all: हल मूल्यों का क्रम क्या स्विफ्ट में प्रलेखन टिप्पणियां या उपकरण हैं? पायथन एंट्री पॉइंट समझाएं? कैसे सी + + में win32 प्रक्रिया निर्माण / समाप्ति पता लगाने के लिए मुझे क्यों "इंडेंटेशन त्रुटि: एक इंडेंट ब्लॉक की उम्मीद" हो रही है? .NET HashTable वीएस डिक्शनरी – क्या डिक्शनरी को तेज़ हो सकता है?

Bash स्क्रिप्ट, stdin पाइप से मूल्य पढ़ें

मैं stdin से डाटा प्रोसेस करने की कोशिश कर रहा हूं जो इसे पाइप करता है, लेकिन कोई भाग्य नहीं, मेरा क्या मतलब है निम्न में से कोई भी कार्य नहीं है:

echo "hello world" | test=($(< /dev/stdin)); echo test=$test test= echo "hello world" | read test; echo test=$test test= echo "hello world" | test=`cat`; echo test=$test test= 

जहां मैं आउटपुट को test=hello world करना चाहता हूं नोट मैंने "$test" चारों ओर उद्धरण चिह्नों को डालने की कोशिश की है जो कि या तो काम नहीं करता है

वेब के समाधान से एकत्रित समाधान "Bash स्क्रिप्ट, stdin पाइप से मूल्य पढ़ें"

उपयोग

 IFS= read var << EOF $(foo) EOF 

आप इस तरह पाइप से स्वीकार करने में read सकते read :

 echo "hello world" | { read test; echo test=$test; } 

या यहां तक ​​कि इस तरह एक फ़ंक्शन लिखें:

 read_from_pipe() { read "$@" <&0; } 

लेकिन कोई बात नहीं है – आपका चर असाइन नहीं हो सकता है! एक पाइपलाइन एक सबशेल्ड पैदा कर सकती है, जहां पर्यावरण को मूल्य से प्राप्त किया जाता है, संदर्भ के अनुसार नहीं। यही कारण है कि read एक पाइप से इनपुट के साथ परेशान नहीं करता है – यह अपरिभाषित है

एफवाईआई, http://www.etalabs.net/sh_tricks.html बोरन के गोले के विषमताओं और असंगतियों से लड़ने के लिए आवश्यक क्रुफ़्ट का निफ्टी संग्रह है, श।

यदि आप बहुत से डेटा में पढ़ना चाहते हैं और प्रत्येक पंक्ति पर अलग से काम करना चाहते हैं तो आप इस तरह से कुछ का उपयोग कर सकते हैं:

 cat myFile | while read x ; do echo $x ; done 

अगर आप लाइनों को कई शब्दों में विभाजित करना चाहते हैं तो आप एक्स के स्थान पर कई चर का उपयोग कर सकते हैं:

 cat myFile | while read xy ; do echo $y $x ; done 

वैकल्पिक रूप से:

 while read xy ; do echo $y $x ; done < myFile 

लेकिन जैसे ही आप इस तरह की चीज़ से वास्तव में चतुर कुछ करना चाहते हैं, आप बेहतर पर्ल की तरह कुछ पटकथा की भाषा के लिए जा रहे हैं, जहां आप इस तरह से कुछ कोशिश कर सकते हैं:

 perl -ane 'print "$F[0]\n"' < myFile 

पर्ल के साथ एक बहुत अधिक सीखने की अवस्था है (या मुझे इनमें से किसी भी भाषा का अनुमान है) लेकिन अगर आप कुछ भी करना चाहते हैं, लेकिन स्क्रिप्ट का सरलतम लेकिन आप इसे लंबे समय तक बहुत आसान पाएंगे मैं पर्ल कुकबुक की सिफारिश करता था और निश्चित रूप से, लैली वॉल एट अल द्वारा पर्ल प्रोग्रामिंग भाषा।

read किसी पाइप से नहीं read जाएगा (या संभवतः परिणाम खो दिया जाता है क्योंकि पाइप एक सबशेल्ड बनाता है)। आप बाश में यहां स्ट्रिंग का उपयोग कर सकते हैं:

 $ read abc <<< $(echo 1 2 3) $ echo $a $b $c 1 2 3 

यह एक और विकल्प है

 $ read test < <(echo hello world) $ echo $test hello world 

मैं बैश में कोई विशेषज्ञ नहीं हूं, लेकिन मुझे आश्चर्य है कि यह प्रस्तावित क्यों नहीं किया गया है:

 stdin=$(cat) echo "$stdin" 

एक-लाइनर सबूत है कि यह मेरे लिए काम करता है:

 $ fortune | eval 'stdin=$(cat); echo "$stdin"' 

bash 4.2 lastpipe विकल्प को प्रस्तुत करता है, जो आपके कोड को लिखित रूप में काम करने की अनुमति देता है, वर्तमान शेल में एक पाइप लाइन में अंतिम आदेश को एक lastpipe के lastpipe करने की अनुमति देता है।

 shopt -s lastpipe echo "hello world" | read test; echo test=$test 

शेल कमांड से एक अन्तर्निहित पाइप के लिए वाक्यविन्यास एक बैश चर में है

 var=$(command) 

या

 var=`command` 

आपके उदाहरणों में, आप असाइनमेंट स्टेटमेंट के लिए डेटा पाइप कर रहे हैं, जो किसी भी इनपुट की अपेक्षा नहीं करता है।

पहला प्रयास बहुत करीब था इस बदलाव को काम करना चाहिए:

 echo "hello world" | { test=$(< /dev/stdin); echo "test=$test"; }; 

और आउटपुट है:

परीक्षण = हैलो दुनिया

परीक्षण और गूंज के लिए असाइनमेंट को संलग्न करने के लिए पाइप के बाद आपको ब्रेसिज़ चाहिए।

ब्रेसिज़ के बिना, परीक्षा (पाइप के बाद) एक शेल में है, और प्रतिध्वनि "परीक्षण = $ परीक्षण" एक अलग शेल में है जो उस असाइनमेंट के बारे में नहीं जानता है। यही कारण है कि आप "test = hello world" के बजाय आउटपुट में "test =" प्राप्त कर रहे थे

मेरी आँखों में stdin से bash में पढ़ने का सबसे अच्छा तरीका निम्नलिखित है, जो आपको इनपुट समाप्त होने से पहले लाइन पर काम करने देता है:

 while read LINE; do echo $LINE done < /dev/stdin 

किसी कार्य को शामिल करने वाली अभिव्यक्ति में कुछ पिपिंग इस तरह से व्यवहार नहीं करता है

इसके बजाय, कोशिश करें:

 test=$(echo "hello world"); echo test=$test 

निम्नलिखित कोड:

 echo "hello world" | ( test=($(< /dev/stdin)); echo test=$test ) 

भी काम करेगा, लेकिन यह पाइप के बाद एक और नए उप-खोल खोल देगा, जहां पर

 echo "hello world" | { test=($(< /dev/stdin)); echo test=$test; } 

नहीं होगा।


मुझे चेप्नर की विधि का उपयोग करने के लिए नौकरी नियंत्रण को अक्षम करना पड़ा (मैं टर्मिनल से यह कमांड चला रहा था):

 set +m;shopt -s lastpipe echo "hello world" | read test; echo test=$test echo "hello world" | test="$(</dev/stdin)"; echo test=$test 

बॉश मैनुअल कहते हैं :

lastpipe

यदि सेट किया गया है, और नौकरी नियंत्रण सक्रिय नहीं है , तो शेल मौजूदा शेल वातावरण में पृष्ठभूमि में निष्पादित नहीं की गई पाइपलाइन के अंतिम आदेश को चलाता है।

नोट: गैर-इंटरैक्टिव शेल में डिफ़ॉल्ट रूप से नौकरी नियंत्रण बंद हो गया है और इस प्रकार आपको स्क्रिप्ट के अंदर set +m आवश्यकता नहीं है।

मुझे लगता है कि आप एक स्क्रिप्ट लिखने का प्रयास कर रहे थे जो stdin से इनपुट ले सकता था। लेकिन जब आप इसे इनलाइन करने के लिए कोशिश कर रहे हैं, तो आप उस परीक्षण = चर बनाने की कोशिश कर खो गए हैं। मुझे लगता है कि यह इनलाइन करने के लिए ज्यादा समझ नहीं लेता है, और यही कारण है कि यह आपकी अपेक्षा के अनुसार काम नहीं करता है।

मैं कम करने की कोशिश कर रहा था

 $( ... | head -n $X | tail -n 1 ) 

विभिन्न इनपुट से एक विशिष्ट पंक्ति प्राप्त करने के लिए इसलिए मैं टाइप कर सकता हूं …

 cat program_file.c | line 34 

इसलिए मुझे स्टडिन से पढ़ने में सक्षम एक छोटा शेल प्रोग्राम चाहिए। जैसे आप करते हैं।

 22:14 ~ $ cat ~/bin/line #!/bin/sh if [ $# -ne 1 ]; then echo enter a line number to display; exit; fi cat | head -n $1 | tail -n 1 22:16 ~ $ 

तुम वहाँ जाओ।

इस बारे में कैसा है:

 echo "hello world" | echo test=$(cat) 

यहां एक वैकल्पिक समाधान है, जिसका इस्तेमाल एक से अधिक चर को पढ़ते समय किया जा सकता है और जब पाइप्स में अधिक शब्द पढ़े जा रहे चर की संख्या से अधिक होते हैं

 eval $(echo hickery dickery dock the mouse | { read ABC ; echo A=\"${A}\" B=\"${B}\" C=\"${C}\" ; }) echo $A hickery echo $B dickery echo $C dock the mouse 

क्योंकि मैं इसके लिए गिरता हूं, मैं एक नोट ड्रॉप करना चाहता हूं। मुझे यह धागा मिला, क्योंकि मुझे पॉसिक्स संगत होने के लिए एक पुरानी श स्क्रिप्ट को फिर से लिखना होगा। इसका मूल रूप से पाइप / सबशेल्ड समस्या को पीओएसआईआईएस द्वारा शुरू किया गया है जो इस तरह से कोड को दोबारा लिखते हैं:

 some_command | read abc 

में:

 read abc << EOF $(some_command) EOF 

और इस तरह कोड:

 some_command | while read abc; do # something done 

में:

 while read abc; do # something done << EOF $(some_command) EOF 

लेकिन बाद में रिक्त इनपुट पर ऐसा व्यवहार नहीं करता है। पुरानी संकेतन के साथ जबकि रिक्त इनपुट पर लूप नहीं दर्ज किया जाता है, लेकिन POSIX संकेतन में यह है! मुझे लगता है कि यह ईओफ़ से पहले नई लाइन के कारण है, जिसे ओमेट नहीं किया जा सकता। पॉसिक्स कोड जो पुराने नोटेशन की तरह व्यवहार करता है, वह इस तरह दिखता है:

 while read abc; do case $a in ("") break; esac # something done << EOF $(some_command) EOF 

ज्यादातर मामलों में यह काफी अच्छा होना चाहिए। लेकिन दुर्भाग्यवश यह अभी भी पुरानी संकेतन की तरह व्यवहार नहीं करता है अगर कुछ_आदेश एक खाली पंक्ति को प्रिंट करता है। पुराने संकेतन में जब शरीर को निष्पादित किया जाता है और पॉसिक्स नोटेशन में हम शरीर के सामने टूटते हैं

इसे ठीक करने के लिए एक ऐसा तरीका दिखाई दे सकता है:

 while read abc; do case $a in ("something_guaranteed_not_to_be_printed_by_some_command") break; esac # something done << EOF $(some_command) echo "something_guaranteed_not_to_be_printed_by_some_command" EOF