पाइप से उपयोगकर्ता इनपुट कैसे पढ़ें?


9

मान लेते हैं कि मेरे पास confirmation.shनिम्नलिखित सामग्री के साथ एक फ़ाइल है:

#!/bin/bash
echo -n "Are you sure [Y/n]? "
read line
case "$line" in
    n|N) echo "smth"
        ;;
    y|Y) echo "smth"
        ;;
esac

और मैं इस स्क्रिप्ट को निम्न तरीके से चलाना चाहता हूं:

cat confirmation.sh | sh

मैं देख रहा हूं Are you sure [Y/n]?और स्क्रिप्ट बाधित है। समस्या क्या है?


2
आपके पास /bin/bashबैंग लाइन में है, फिर भी आप एक .shएक्सटेंशन का उपयोग करते हैं और स्क्रिप्ट को पाइप करने की कोशिश करते हैं sh। एक समस्या नहीं है क्योंकि आपके पास कोड दोनों के साथ संगत है, लेकिन इंगित करने के लायक है।
ग्रीम

जवाबों:


8

के रूप में अन्य लोगों ने कहा, इस वजह से है stdinकी shपाइप से पढ़ने के लिए पुनः निर्देशित किया गया है, यह टर्मिनल से जुड़ा नहीं है के रूप में यह सामान्य रूप से होगा। एक चीज जो आप इसके आसपास प्राप्त कर सकते हैं /dev/ttyवह है टर्मिनल से पढ़ने के लिए स्क्रिप्ट को मजबूर करने के लिए उपयोग करना। उदाहरण के लिए:

#!/bin/sh

read -p "Are you sure [Y/n]?" line </dev/tty
case "$line" in
  y|Y) echo "confirmed"
    ;;
  *) echo "not confirmed"
    ;;
esac

आम तौर पर आप ऐसा तभी करेंगे जब आप विशेष रूप से लोगों को इनपुट की स्क्रिप्टिंग से रोकना चाहते हैं, जैसे:

echo Y | sh confirmation.sh

यह तब भी टर्मिनल से पढ़ा जाएगा, भले ही उपयोगकर्ता Yको तुरंत प्रॉम्प्ट पर यह इनपुट करने की उम्मीद हो । यह उन कार्यक्रमों के लिए आम है जो एक पासवर्ड से ऐसा करने की अपेक्षा करते हैं।


2
sh 3<<CONFIRM /dev/fd/3
    $(cat ./confirmation.sh)
CONFIRM

sh 3<./confirmation.sh /dev/fd/3

नोट: उपरोक्त दो उदाहरणों में मुझे सही करने के लिए @Gememe का धन्यवाद ...

यदि आप stdinस्पष्ट रखते हैं तो यह बहुत आसान है ।

2<./confirmation.sh . /dev/stderr

या, चूंकि एक टर्मिनल 0 0 2 सभी समान फ़ाइल हैं, बस जोड़ें:

read line <&2

और आपका

cat ./confirmation.sh | sh

ठीक काम करता है।


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

अजीब है, वे सभी मेरे लिए काम करते थे ... मैं किसी चीज के बीच में हूं, लेकिन ... 10 या इतने मिनट में मैं फिर से परीक्षण कर सकता हूं। इस बीच ... शायद अपनी टिप्पणी को बोल्ड करें ? मुझे गलत सूचना प्रसारित करना पसंद नहीं है।
मोकेसर

@Graeme - यह सुनिश्चित नहीं था कि मैं इसे पहली बार क्यों याद किया - शपथ ले सकता था मैंने एक ही समय में उन सभी का परीक्षण किया - लेकिन पहले दो को सही ढंग से संचालित करने के लिए एक बदलाव की आवश्यकता है। धन्यवाद।
mikeserv

अच्छा लगता है, यह तब भी टर्मिनल से नहीं पढ़ता है जब मैं stderrहालांकि स्रोत से । मुझे शायद हालांकि, मुझे समझ नहीं आता कि क्यों।
ग्रीम

@ ग्रेमी - अजीब - मैंने इसे डैश श zsh और बैश के साथ आजमाया। सभी ने काम किया।
मोकेसर

0

इसने एक ही तर्क के लिए मेरी पटकथा पर काम किया है:

if [ -p /dev/stdin ]; then set -- "$( cat )"; fi

फिर मैं एक स्थैतिक तर्क ( $1) में पाइप किए गए डेटा तक पहुंच सकता हूं , जो मेरे अन्य स्क्रिप्ट कामकाज के साथ संगत है।


से info test:

[ -p /dev/stdin ]: -p FILEयदि FILE मौजूद है तो यह सही है और एक नामित पाइप है।


-1

संक्षिप्त उत्तर यह है कि आप नहीं कर सकते। पाइप स्टडआउट को रीडायरेक्ट करता है, इसलिए आप एक इंटरेक्टिव स्क्रिप्ट नहीं चला सकते, क्योंकि आपने पहले से आउटपुट को रीडायरेक्ट कर दिया है और पाइप स्टेटमेंट में दूसरी कमांड के इनपुट के रूप में।

आप ऐसा कुछ करना चाह रहे होंगे:

cat confirmation.sh > ask.sh && sh ask.sh

आप अभी भी एक इंटरैक्टिव स्क्रिप्ट चला सकते हैं, मेरा जवाब देखें। इसके अलावा, सिर्फ क्यों नहीं sh confirmation.sh?
ग्रीम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.