न्यूमेरिक रेंज में लेटर ग्रेड असाइन करने के लिए शेल स्क्रिप्ट कैसे लिखें?


19

मैं एक स्क्रिप्ट बनाना चाहता हूं जो आपको 0-100 के बीच की संख्या के लिए संकेत दे और फिर आपको संख्या के आधार पर ग्रेड दे।

मुझे यह पसंद है।

PS3='Please enter your choice: '
(Something here)

do
case $
    "0-59")
        echo "F"
        ;;
    "60-69")
        echo "D"
        ;;
    "70-79")
        echo "C"
        ;;
    "Quit")
        break
        ;;
    *) echo invalid option;;
esac
done

जवाबों:


20

ब्रेविटी बनाम पठनीयता: एक मध्य मैदान

जैसा कि आपने देखा है, यह समस्या उन समाधानों को स्वीकार करती है जो मध्यम लंबे और कुछ हद तक दोहराए जाने वाले हैं, लेकिन बहुत पठनीय हैं ( टेर्डन और एबी के बाश उत्तर), साथ ही साथ वे जो बहुत कम लेकिन गैर-सहज और बहुत कम स्व-दस्तावेजीकरण (टिम पायथन) हैं और बैश जवाब और ग्लेन जैकमैन के पर्ल जवाब )। ये सभी दृष्टिकोण मूल्यवान हैं।

आप इस समस्या को कॉम्पैक्टनेस और पठनीयता के बीच निरंतरता के बीच में कोड के साथ भी हल कर सकते हैं। यह दृष्टिकोण लगभग लंबे समाधानों के रूप में पठनीय है, छोटे, गूढ़ समाधानों की लंबाई के साथ।

#!/usr/bin/env bash

read -erp 'Enter numeric grade (q to quit): '
case $REPLY in [qQ]) exit;; esac

declare -A cutoffs
cutoffs[F]=59 cutoffs[D]=69 cutoffs[C]=79 cutoffs[B]=89 cutoffs[A]=100

for letter in F D C B A; do
    ((REPLY <= cutoffs[$letter])) && { echo $letter; exit; }
done
echo "Grade out of range."

इस बैश समाधान में, मैंने पठनीयता बढ़ाने के लिए कुछ रिक्त लाइनें शामिल की हैं, लेकिन यदि आप इसे और भी कम चाहते हैं तो आप उन्हें हटा सकते हैं।

खाली लाइनों को शामिल किया गया, यह वास्तव में एबी के बैश समाधान के एक कॉम्पैक्ट, अभी भी बहुत पठनीय संस्करण की तुलना में थोड़ा कम है । उस पद्धति पर इसके मुख्य लाभ हैं:

  • यह अधिक सहज है।
  • ग्रेड के बीच की सीमाओं को बदलना आसान है (या अतिरिक्त ग्रेड जोड़ें)।
  • यह स्वचालित रूप से प्रमुख और अनुगामी रिक्त स्थान के साथ इनपुट को स्वीकार करता है (कैसे (( ))काम करता है की व्याख्या के लिए नीचे देखें )।

ये सभी तीन फायदे हैं क्योंकि यह विधि उपयोगकर्ता के इनपुट को संख्यात्मक डेटा के रूप में उपयोग करती है बजाय इसके घटक अंकों को मैन्युअल रूप से जांचने के लिए।

यह काम किस प्रकार करता है

  1. उपयोगकर्ता से इनपुट पढ़ें। उन्हें तीर कुंजी का उपयोग उनके द्वारा दर्ज किए गए पाठ में घूमने के लिए करें ( -e) और \एक एस्केप चरित्र के रूप में व्याख्या न करें ( -r)।
    यह स्क्रिप्ट एक सुविधा संपन्न समाधान नहीं है - एक शोधन के लिए नीचे देखें - लेकिन वे उपयोगी विशेषताएं केवल इसे दो अक्षर लंबे समय तक बनाती हैं। मैं हमेशा के -rसाथ उपयोग करने की सलाह देता हूं read, जब तक कि आपको नहीं पता कि आपको उपयोगकर्ता की आपूर्ति से \बचने की आवश्यकता है।
  2. यदि उपयोगकर्ता ने लिखा है qया Qछोड़ दिया है।
  3. एक साहचर्य सरणी बनाएँ ( declare -A)। प्रत्येक अक्षर ग्रेड के साथ जुड़े उच्चतम संख्यात्मक ग्रेड के साथ इसे आबाद करें।
  4. पत्र ग्रेड के माध्यम से निम्नतम से उच्चतम तक की जाँच करें, अगर उपयोगकर्ता द्वारा प्रदान की गई संख्या प्रत्येक अक्षर ग्रेड की संख्यात्मक सीमा में गिरने के लिए पर्याप्त है। अंकगणितीय मूल्यांकन के
    साथ (( )), चर नामों के साथ विस्तार करने की आवश्यकता नहीं है $। (अधिकांश अन्य स्थितियों में, यदि आप इसके नाम के स्थान पर किसी चर के मान का उपयोग करना चाहते हैं, तो आपको यह अवश्य करना चाहिए ।)
  5. यदि यह सीमा में आता है, तो ग्रेड प्रिंट करें और बाहर निकलें
    संक्षिप्तता के लिए, मैं शॉर्ट सर्किट का उपयोग और ऑपरेटर ( &&बल्कि एक से) if- then
  6. यदि लूप खत्म हो जाता है और कोई रेंज मैच नहीं हुई है, तो मान लें कि दर्ज की गई संख्या बहुत अधिक है (100 से अधिक) और उपयोगकर्ता को बताएं कि यह सीमा से बाहर है।

यह कैसे अजीब है, अजीब इनपुट के साथ

पोस्ट किए गए अन्य छोटे समाधानों की तरह , यह स्क्रिप्ट एक संख्या मानने से पहले इनपुट की जांच नहीं करती है। अंकगणित मूल्यांकन ( (( ))) स्वचालित रूप से प्रमुख और रिक्त स्थान को अनुगामी स्ट्रिप्स, इसलिए है कि कोई समस्या नहीं है, लेकिन:

  • इनपुट जो किसी संख्या की तरह नहीं दिखता है उसे 0 के रूप में व्याख्या किया गया है।
  • इनपुट के साथ जो एक संख्या की तरह दिखता है (यानी, यदि यह एक अंक से शुरू होता है) लेकिन इसमें अमान्य वर्ण हैं, तो स्क्रिप्ट त्रुटियों का उत्सर्जन करती है।
  • मल्टी अंकों इनपुट के साथ शुरू 0किया गया है किया जा रहा है के रूप में व्याख्या में अष्टाधारी । उदाहरण के लिए, स्क्रिप्ट आपको बताएगी 77 एक सी है, जबकि 077 एक डी है। हालांकि कुछ उपयोगकर्ता यह चाहते हैं, सबसे अधिक शायद नहीं और यह भ्रम पैदा कर सकता है।
  • प्लस साइड पर, जब एक अंकगणितीय अभिव्यक्ति दी जाती है, तो यह स्क्रिप्ट स्वचालित रूप से इसे सरल बनाती है और संबंधित पत्र ग्रेड को निर्धारित करती है। उदाहरण के लिए, यह आपको बताएगा कि 320/4 एक बी है।

एक विस्तारित, पूरी तरह से चित्रित संस्करण

उन कारणों के लिए, आप इस विस्तारित स्क्रिप्ट की तरह कुछ का उपयोग करना चाह सकते हैं, जो यह सुनिश्चित करने के लिए जांचता है कि इनपुट अच्छा है, और कुछ अन्य संवर्द्धन भी शामिल हैं।

#!/usr/bin/env bash
shopt -s extglob

declare -A cutoffs
cutoffs[F]=59 cutoffs[D]=69 cutoffs[C]=79 cutoffs[B]=89 cutoffs[A]=100

while read -erp 'Enter numeric grade (q to quit): '; do
    case $REPLY in  # allow leading/trailing spaces, but not octal (e.g. "03") 
        *( )@([1-9]*([0-9])|+(0))*( )) ;;
        *( )[qQ]?([uU][iI][tT])*( )) exit;;
        *) echo "I don't understand that number."; continue;;
    esac

    for letter in F D C B A; do
        ((REPLY <= cutoffs[$letter])) && { echo $letter; continue 2; }
    done
    echo "Grade out of range."
done

यह अभी भी एक सुंदर कॉम्पैक्ट समाधान है।

यह क्या सुविधाएँ जोड़ता है?

इस विस्तारित स्क्रिप्ट के मुख्य बिंदु हैं:

  • इनपुट सत्यापन टेरडॉन की स्क्रिप्ट इनपुट की जांच करती है , इसलिए मैं एक और तरीका दिखाता हूं, जो कुछ संक्षिप्तता का त्याग करता है, लेकिन अधिक मजबूत होता है, जिससे उपयोगकर्ता अग्रणी और अनुगामी स्थानों में प्रवेश कर सकता है और एक अभिव्यक्ति की अनुमति देने से इनकार कर सकता है जो ऑक्टल के रूप में अभिप्रेत नहीं हो सकती है (जब तक कि शून्य नहीं है) ।if [[ ! $response =~ ^[0-9]*$ ]] ...
  • मैं का उपयोग किया है caseके साथ ग्लोबिंग विस्तारित बजाय [[साथ =~ नियमित अभिव्यक्ति मिलान (के रूप में ऑपरेटर terdon का जवाब )। मैंने ऐसा करने के लिए (और कैसे) यह भी किया जा सकता है। ग्लोब और रेगेक्स, पाठ से मेल खाने वाले पैटर्न को निर्दिष्ट करने के दो तरीके हैं, और या तो विधि इस एप्लिकेशन के लिए ठीक है।
  • जैसा अटल बिहारी के bash स्क्रिप्ट , मैं एक बाहरी पाश में पूरी बात (के प्रारंभिक निर्माण को छोड़कर संलग्न किया है cutoffsसरणी)। यह संख्याओं का अनुरोध करता है और टर्मिनल इनपुट उपलब्ध होने तक संबंधित पत्र ग्रेड देता है और उपयोगकर्ता ने इसे छोड़ने के लिए नहीं कहा है। आपके प्रश्न में कोड के आसपास do... देखकर done, ऐसा लगता है कि आप ऐसा चाहते हैं।
  • छोड़ने को आसान बनाने के लिए, मैं किसी भी मामले को असंवेदनशील qया स्वीकार करता हूं quit

यह स्क्रिप्ट कुछ निर्माणों का उपयोग करती है जो नौसिखियों के लिए अपरिचित हो सकते हैं; वे नीचे विस्तृत हैं।

स्पष्टीकरण: का उपयोग continue

जब मैं बाहरी whileलूप के शेष शरीर को छोड़ना चाहता हूं , तो मैं continueकमांड का उपयोग करता हूं । यह इसे लूप के शीर्ष पर वापस लाता है, अधिक इनपुट पढ़ने और एक और पुनरावृत्ति चलाने के लिए।

पहली बार जब मैं ऐसा करता हूं, तो मैं जो एकमात्र लूप होता हूं वह बाहरी whileलूप होता है, इसलिए मैं continueबिना किसी तर्क के कॉल कर सकता हूं । (मैं एक में हूँ caseनिर्माण, लेकिन उस के संचालन को प्रभावित नहीं करता है breakया continue।)

        *) echo "I don't understand that number."; continue;;

हालांकि, दूसरी बार, मैं एक आंतरिक forलूप में हूं जो खुद बाहरी whileलूप के अंदर नेस्टेड है । अगर मैं continueबिना किसी तर्क के उपयोग करता हूं , तो यह बराबर continue 1होगा और forबाहरी whileलूप के बजाय आंतरिक लूप जारी रखेगा ।

        ((REPLY <= cutoffs[$letter])) && { echo $letter; continue 2; }

तो उस स्थिति में, मैं continue 2बैश खोजने और दूसरे लूप को जारी रखने के लिए उपयोग करता हूं ।

स्पष्टीकरण: caseग्लब्स के साथ लेबल

मैं यह caseपता लगाने के लिए उपयोग नहीं करता हूं कि कौन से अक्षर ग्रेड बिन एक संख्या में गिरता है (जैसे एबी के बैश उत्तर में )। लेकिन मैं यह caseतय करने के लिए उपयोग करता हूं कि क्या उपयोगकर्ता के इनपुट पर विचार किया जाना चाहिए:

  • एक वैध संख्या, *( )@([1-9]*([0-9])|+(0))*( )
  • पद छोड़ना, *( )[qQ]?([uU][iI][tT])*( )
  • कुछ और (और इस तरह अमान्य इनपुट), *

ये शेल ग्लब्स हैं

  • प्रत्येक के बाद एक है )कि किसी भी उद्घाटन से मेल नहीं खाता है (, जो caseकि जब यह मिलान होता है तब चलने वाले आदेशों से एक पैटर्न को अलग करने के लिए वाक्यविन्यास है।
  • ;;है caseएक paticular मामले मैच के लिए चलाने के लिए (और है कि बाद में कोई मामलों उन्हें चलाने के बाद परीक्षण किया जाना चाहिए) आदेशों के अंत का संकेत के लिए की वाक्य रचना।

साधारण गोलाकार गोलाकार *शून्य या अधिक वर्णों का मिलान करने के लिए प्रदान करता है, ?बिलकुल एक वर्ण और [ ]कोष्ठक में वर्ण वर्गों / श्रेणियों से मेल खाने के लिए । लेकिन मैं विस्तारित ग्लोबिंग का उपयोग कर रहा हूं , जो उससे आगे जाता है। bashअंतःक्रियात्मक रूप से उपयोग करते समय विस्तारित ग्लोबिंग डिफ़ॉल्ट रूप से सक्षम होता है , लेकिन स्क्रिप्ट चलाते समय डिफ़ॉल्ट रूप से अक्षम होता है। shopt -s extglobस्क्रिप्ट के शीर्ष पर आदेश उस पर बदल जाता है।

स्पष्टीकरण: विस्तारित ग्लोबिंग

*( )@([1-9]*([0-9])|+(0))*( ), जो संख्यात्मक इनपुट के लिए जाँच करता है , के अनुक्रम से मेल खाता है:

  • शून्य या अधिक रिक्त स्थान ( *( ))। *( )निर्माण मैचों शून्य या कोष्ठक में पैटर्न, सिर्फ एक जगह नहीं है यहाँ जिनमें से अधिक।
    वास्तव में दो प्रकार के क्षैतिज व्हाट्सएप, स्पेस और टैब हैं, और अक्सर यह टैब से मिलान करने के लिए भी वांछनीय है। लेकिन मैं यहाँ उस बारे में चिंता नहीं कर रहा हूँ, क्योंकि यह स्क्रिप्ट मैन्युअल, इंटरेक्टिव इनपुट और -eझंडे को readGNU रीडलाइन को सक्षम करने के लिए लिखा गया है। ऐसा इसलिए है कि उपयोगकर्ता अपने पाठ में बाएं और दाएं तीर कुंजियों के साथ आगे-पीछे हो सकता है, लेकिन इसमें आम तौर पर टैब को शाब्दिक रूप से प्रवेश करने से रोकने का दुष्प्रभाव है।
  • दोनों में से एक घटना @( )( |):
    • एक अंकीय अंक ( [1-9]) शून्य या अधिक ( *( )) किसी भी अंक ( [0-9]) के बाद।
    • एक या अधिक ( +( )) का 0
  • शून्य या अधिक रिक्त स्थान ( *( )), फिर से।

*( )[qQ]?([uU][iI][tT])*( ), जो छोड़ दिया आदेश के लिए जाँच करता है , के एक क्रम से मेल खाता है:

  • शून्य या अधिक रिक्त स्थान ( *( ))।
  • qया Q( [qQ])।
  • वैकल्पिक रूप से - अर्थात, शून्य या एक घटना ( ?( )) का:
    • uया U( [uU]) के बाद iया I( [iI]) के बाद tया T( [tT])।
  • शून्य या अधिक रिक्त स्थान ( *( )), फिर से।

वेरिएंट: एक विस्तारित नियमित अभिव्यक्ति के साथ वैधता इनपुट

आप एक खोल ग्लोब के बजाय एक नियमित अभिव्यक्ति के खिलाफ उपयोगकर्ता के इनपुट परीक्षण करने के लिए पसंद करते हैं, तो आप इस संस्करण है, जो एक ही है, लेकिन का उपयोग करता है काम करता है का उपयोग करना पसंद कर सकते हैं [[और =~(जैसे में terdon का जवाब ) के बजाय caseऔर ग्लोबिंग बढ़ाया।

#!/usr/bin/env bash
shopt -s nocasematch

declare -A cutoffs
cutoffs[F]=59 cutoffs[D]=69 cutoffs[C]=79 cutoffs[B]=89 cutoffs[A]=100

while read -erp 'Enter numeric grade (q to quit): '; do
    # allow leading/trailing spaces, but not octal (e.g., "03")
    if [[ ! $REPLY =~ ^\ *([1-9][0-9]*|0+)\ *$ ]]; then
        [[ $REPLY =~ ^\ *q(uit)?\ *$ ]] && exit
        echo "I don't understand that number."; continue
    fi

    for letter in F D C B A; do
        ((REPLY <= cutoffs[$letter])) && { echo $letter; continue 2; }
    done
    echo "Grade out of range."
done

इस दृष्टिकोण के संभावित लाभ इस प्रकार हैं:

  • इस विशेष मामले में, वाक्यविन्यास थोड़ा सरल है, कम से कम दूसरे पैटर्न में, जहां मैं छोड़ दिया कमांड के लिए जांच करता हूं। इसका कारण यह है कि मैं सेट करने में सक्षम था nocasematchखोल विकल्प, और तब सभी मामले की वेरिएंट qऔर quitस्वचालित रूप से कवर किया गया।

    वही shopt -s nocasematchकाम करता है। shopt -s extglobआदेश ग्लोबिंग इस संस्करण में नहीं किया जाता है के रूप में छोड़ दिया जाता है।

  • बैश के एक्सग्लोब में प्रवीणता की तुलना में नियमित अभिव्यक्ति कौशल अधिक सामान्य हैं।

स्पष्टीकरण: नियमित अभिव्यक्तियाँ

=~ऑपरेटर के दाईं ओर निर्दिष्ट किए गए पैटर्न के लिए , यहां बताया गया है कि उन नियमित अभिव्यक्तियाँ कैसे काम करती हैं।

^\ *([1-9][0-9]*|0+)\ *$, जो संख्यात्मक इनपुट के लिए जाँच करता है , के अनुक्रम से मेल खाता है:

  • शुरुआत - यानी, बाएं किनारे - लाइन की ( ^)।
  • शून्य या अधिक ( *, लागू पोस्टफ़िक्स) रिक्त स्थान। एक स्थान को \नियमित रूप से अभिव्यक्ति में नियमित रूप से होने की आवश्यकता नहीं है , लेकिन [[एक सिंटैक्स त्रुटि को रोकने के लिए इसके साथ की आवश्यकता है ।
  • एक विकल्प ( ( )) जो एक या दूसरे का है ( |):
    • [1-9][0-9]*: किसी अंक का [1-9]शून्य या उससे अधिक ( *, अनुप्रयुक्त पोस्टफिक्स) के बाद एक नोनोजेरो अंक ( [0-9])।
    • 0+: एक या अधिक ( +के, लागू पोस्टफ़िक्स) 0
  • पहले की तरह शून्य या अधिक स्थान ( \ *)।
  • अंत - यानी, दाहिने किनारे - लाइन का ( $)।

caseलेबल्स के विपरीत , जो पूरी अभिव्यक्ति के परीक्षण के विरुद्ध मेल खाता है, यह =~सही है अगर इसके बाएं हाथ के किसी भी हिस्से को उसके दाहिने हाथ की अभिव्यक्ति के रूप में दिए गए पैटर्न से मेल खाता है। यही कारण है कि ^और $एंकर, लाइन की शुरुआत और अंत को निर्दिष्ट करते हैं, यहां आवश्यक हैं, और इसके साथ caseऔर एक्सग्लब्स के साथ विधि में प्रकट होने वाली किसी भी चीज़ के लिए वाक्यात्मक रूप से मेल नहीं खाते हैं।

कोष्ठक बनाने के लिए ^और $के विच्छेदन के लिए बाध्य करने के लिए आवश्यक हैं [1-9][0-9]*और 0+। अन्यथा यह की अलगाव हो जाएगा ^[1-9][0-9]*और 0+$, और किसी भी इनपुट से मेल एक अशून्य अंकों के साथ शुरू या एक के साथ समाप्त 0(या दोनों, जो अभी भी बीच में गैर अंक शामिल हो सकता है)।

^\ *q(uit)?\ *$, जो छोड़ दिया आदेश के लिए जाँच करता है , के एक क्रम से मेल खाता है:

  • लाइन की शुरुआत ( ^)।
  • शून्य या अधिक रिक्त स्थान ( \ *, स्पष्टीकरण के ऊपर देखें)।
  • अक्षर q। या Q, चूंकि shopt nocasematchसक्षम है।
  • वैकल्पिक रूप से - यानी, शून्य या एक घटना (उपसर्ग ?) - सबस्ट्रिंग ( ( )) की:
    • u, उसके बाद i, उसके बाद t। या, shopt nocasematchसक्षम uहोने के बाद से हो सकता है U; स्वतंत्र रूप से, iहो सकता है I; और स्वतंत्र रूप से, tहो सकता है T। (अर्थात्, संभावनाएँ सीमित नहीं हैं uitऔर UIT)
  • शून्य या अधिक रिक्त स्थान फिर से ( \ *)।
  • पंक्ति का अंत ( $)।

3
मुझे सच बताओ .. कितना समय लगा है? ;)
हेमायल

4
@heemayl मुझे पूरी तरह से यकीन नहीं है, क्योंकि मैंने इसे दिन भर में कई छोटे हिस्सों में लिखा है (पोस्टिंग से पहले एक पूर्ण रीड-थ्रू और संपादन के बाद)। मुझे पूरा यकीन है कि जब मैंने शुरू किया था, तो मुझे जितना समय लगा होगा, उससे अधिक समय लगेगा, हालांकि, अगर मैं सोच रहा था कि इसे लेने में कितना समय लगेगा। :)
एलिया कगन

6
अधिक से अधिक लिखें, मुझे आपके उत्तरों की एक पुस्तक चाहिए।
बृजेश चौहान

TL, डॉ। लेकिन मुझे वैसे भी हँसाया!
फाबबी

शीर्षक से लेकर स्पष्टीकरण तक सब कुछ अच्छा है। मैं इसे पहली बार में समझ गया था, लेकिन मैंने इसे फिर से सिर्फ इसलिए पढ़ा क्योंकि मैं चाहता था
सुमीत देशमुख

23

आपके पास पहले से ही मूल विचार है। यदि आप इसे कोड करना चाहते हैं bash(जो कि एक उचित विकल्प है क्योंकि यह उबंटू और अधिकांश अन्य लिनक्स पर डिफ़ॉल्ट शेल है), तो आप इसका उपयोग नहीं कर सकते caseक्योंकि यह श्रेणियों को नहीं समझता है। इसके बजाय, आप उपयोग कर सकते हैं if/ else:

#!/usr/bin/env bash

read -p "Please enter your choice: " response

## If the response given did not consist entirely of digits
if [[ ! $response =~ ^[0-9]*$ ]]
then
    ## If it was Quit or quit, exit
    [[ $response =~ [Qq]uit ]] && exit
    ## If it wasn't quit or Quit but wasn't a number either,
    ## print an error message and quit.
    echo "Please enter a number between 0 and 100 or \"quit\" to exit" && exit
fi
## Process the other choices
if [ $response -le 59 ]
then
    echo "F"
elif [ $response -le 69 ]
then
    echo "D"
elif  [ $response -le 79 ]
then
    echo "C"
elif  [ $response -le 89 ]
then
    echo "B"
elif [ $response -le 100 ]
then
    echo "A"
elif [ $response -gt 100 ]
then
    echo "Please enter a number between 0 and 100"
     exit
fi

4
-geजब से आप उपयोग कर रहे हैं, उन परीक्षणों का एक गुच्छा समाप्त हो सकता है elif। और कोई प्यार के लिए (( $response < X ))?
मूरू

2
@ मरमू सच, धन्यवाद। मैं संख्या सीमाओं में सोच रहा था, लेकिन कोई कारण नहीं था। के रूप में (( $response < X )), यकीन है, लेकिन मुझे यह स्पष्ट है और ओपी स्पष्ट रूप से पटकथा को कोसने के लिए नया है।
टेराडॉन

12
#!/bin/bash

while true
do
  read -p "Please enter your choice: " choice

  case "$choice"
   in
      [0-9]|[1-5][0-9])
          echo "F"
          ;;
      6[0-9])
          echo "D"
          ;;
      7[0-9])
          echo "C"
          ;;
      8[0-9])
          echo "B"
          ;;
      9[0-9]|100)
          echo "A"
          ;;
      [Qq])
          exit 0
          ;;
      *) echo "Only numbers between 0..100, q for quit"
          ;;
  esac
done

और अधिक कॉम्पैक्ट संस्करण (Thx @EliahKagan ):

#!/usr/bin/env bash

while read -erp 'Enter numeric grade (q to quit): '; do
    case $REPLY in
        [0-9]|[1-5][0-9])   echo F ;;
        6[0-9])             echo D ;;
        7[0-9])             echo C ;;
        8[0-9])             echo B ;;
        9[0-9]|100)         echo A ;;

        [Qq])               exit ;;
        *)                  echo 'Only numbers between 0..100, q for quit' ;;
    esac
done

1
वे चरित्र श्रेणियां हैं, निश्चित रूप से? अर्थात [0-59]0,1,2,3,4,5 या 9 और इसी तरह से कोई भी वर्ण। मैं यह नहीं देखता कि संख्यात्मक मान के लिए यह कैसे काम कर सकता है ।
स्टीलड्राइवर

3
आपको हर समय FGITW होना जरूरी नहीं है। आप समय लें, अच्छे उत्तर लिखें। देखें कि टेराडो या एलिया कगन कैसे काम करते हैं।
मूरू

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

9

सभी उबंटू इंस्टॉल में पायथन है, इसलिए यहां एक पायथन स्क्रिप्ट एक लाइनर है। यदि आपको इसे बाश में रखने की आवश्यकता है, तो मैंने शेल स्क्रिप्ट के बराबर भी लिखा है

print (chr(75-max(5,int('0'+raw_input('Enter the number: ')[:-1]))))

चलाने के लिए, इसे किसी फ़ाइल में सहेजें (उदाहरण के लिए grade.py) और फिर इसे इसके साथ टर्मिनल में चलाएँ:

python grade.py

आप यह देख पाएंगे:

Enter the number: 65
E

यह कैसे काम करता है?

  1. इनपुट ले लो - 65
  2. शुरुआत में 0 जोड़ें - 065
  3. अंतिम चार निकालें - 06
  4. 75 उस संख्या को घटाएं - 70
  5. एक अक्षर में परिवर्तित करें (ए 65 है, बी 66 है) - E
  6. इसे प्रिंट करें - E

मेरे सर्वनाम वह / उसके हैं


मुझे आपका विचार पसंद है। +1
एबी

उपयोग न करें input(), यह कॉल करेगा, इसके बजाय eval()उपयोग raw_input()करें..तो आपकी ग्रेडिंग सही नहीं है क्योंकि 90+ग्रेड प्रिंट Bहोगा..उसे chr(74 - max(4, num))....
heemayl

well..your समाधान अच्छा है और परिवर्तन also..just को Python2 में काम करेंगे input()करने के लिए raw_input()python2..thats के लिए यह ..
heemayl

print chr(75-max(5,int('0'+raw_input('Enter the number: ')[:-1])))
हेमायला

फिर आपको अपना मूल कोड भी बदलने की जरूरत है..आपका संशोधित कोड क्योंकि यह वर्तमान में खड़ा है, हालांकि गलत python3नहीं है raw_input().. जैसा कि मैंने raw_input()अपने शुरुआती एक के लिए सुझाया है जैसा कि आपने इसे चलाने के लिए कहा है python2..
heemayl

6

यहाँ मेरा अर्ध- बैरिक बैश समाधान है, जो 101 प्रविष्टियों के साथ एक सरणी को पॉप्युलेट करता है और फिर उनके खिलाफ उपयोगकर्ता इनपुट की जाँच करता है। यहां तक ​​कि वास्तविक दुनिया के उपयोग के लिए यह उचित है - यदि आपको उत्कृष्ट प्रदर्शन की आवश्यकता है तो आप बैश का उपयोग नहीं करेंगे, और सौ (या तो) असाइनमेंट अभी भी तेज हैं। लेकिन इसे एक बड़ी रेंज (जैसे एक लाख) तक बढ़ाया जाना उचित होगा।

#!/usr/bin/env bash
p(){ for i in `seq $2 $3`; do g[$i]=$1; done; }
p A 90 100; p B 80 89; p C 70 79; p D 60 69; p F 0 59
while read -r n && [[ ! $n =~ ^[qQ] ]]; do echo ${g[$n]}; done

लाभ:

  • यह वास्तव में गूढ़ नहीं है। हालांकि यह सबसे छोटे समाधानों की तुलना में लंबा है, और लंबे समाधानों के रूप में स्व-दस्तावेजीकरण के रूप में नहीं है ... यह यथोचित स्व-दस्तावेजीकरण है , जबकि अभी भी छोटे पक्ष पर तय किया गया है।
  • यह ग्रेड सीमाओं को बदलने या ग्रेड को जोड़ने / हटाने के लिए आसान संशोधन की अनुमति देता है।
  • यह एक पाश और पर इस्तीफा में चल रही है q, quitया के साथ शुरू कुछ भी q/ Q
  • उच्च ग्रेड को पहले सूचीबद्ध करता है, जिससे आप सकारात्मक सोच सकें। :)
  • हम्म, यह काम करता है, आप इसे देखने के बाद भी समझ में आता है, और आवश्यक विशेषताएं हैं। आप वास्तव में इस का उपयोग कर सकते हैं!

नुकसान:

  • जब आप गैर-संख्यात्मक इनपुट में डालते हैं तो यह आपको एक एफ देता है ... लेकिन यह वास्तव में इतना बुरा नहीं है, है ना? यदि आप एक गैर-संख्या देते हैं जहां एक नंबर की आवश्यकता होती है, तो शायद आप एक एफ के लायक हैं!
  • अस्पष्ट, संभवतः अष्टाधारी इनपुट अष्टाधारी के रूप में व्यवहार किया जाता है (के बाद से gएक है एक आयामी अनुक्रमित सरणी )। जैसा कि पुरानी कहावत है, "यह एक बग नहीं है, यह एक विशेषता है!" शायद हो सकता है।
  • इनपुट जो कि सीमा से बाहर है या संख्या नहीं है, एक खाली रेखा मुद्रित होने का कारण बनती है। हालांकि इसमें वास्तव में कुछ भी गलत नहीं है: यह आपको बताता है कि आपके इनपुट के अनुरूप कौन सा अक्षर ग्रेड है, और गलत इनपुट के लिए कोई नहीं है।
  • एक नकारात्मक संख्या में रखो, और यह ... ठीक है, इसे एक ईस्टर अंडे कहते हैं
  • टिम के अजगर समाधान की तुलना में अभी भी काफी लंबा है । हाँ, मैं वास्तव में ऐसा नहीं कर सकता कि एक फायदा हो।

किन्दा कूल, हुह? (मैं ये सोचता हूँ।)

यह काम किस प्रकार करता है

  1. यह pफ़ंक्शन p अपने तीसरे तर्क में दिए गए (अक्षर) मान के साथ, इसके पहले तर्क से दूसरे तक के अनुक्रमित पर, जी राड्स के एक संख्यात्मक रूप से अनुक्रमित सरणी gको दर्शाता है।
  2. p प्रत्येक अक्षर ग्रेड के लिए कहा जाता है, इसकी संख्यात्मक सीमा को परिभाषित करने के लिए।
  3. उपयोगकर्ता इनपुट को तब तक पढ़ते रहें जब तक यह उपलब्ध है और q(या Q) के साथ शुरू नहीं होता है , उस gसरणी की जांच करना जिसके लिए पत्र ग्रेड दर्ज की गई संख्या से मेल खाती है, और उस पत्र को प्रिंट करना।

इस सशर्त के बारे में क्या? [[ $n =~ ^(0|[1-9]+[0-9]*)$ ]]
हेलियो

6

पायथन 2 में बनाने के बाद , मैंने इसे बैश में बनाने का फैसला किया।

#! /bin/bash

read -p "Enter the number: " i
i=0$i
x=$((10#${i::-1}))
printf "\x$(printf %x $((11-($x>5?$x:5)+64)))\n"

चलाने के लिए, इसे एक फ़ाइल (जैसे ग्रेड.श) में सहेजें, इसे निष्पादन योग्य बनाएं chmod +x grade.shऔर फिर साथ चलाएं ./grade.sh

आप यह देख पाएंगे:

Enter the number: 65
E

यह कैसे काम करता है?

  1. इनपुट ले लो - 65
  2. शुरुआत में 0 जोड़ें - 065(और 10#यह आधार 10 रखता है)।
  3. अंतिम चार निकालें - 06
  4. 75 उस संख्या को घटाएं - 70
  5. एक अक्षर में परिवर्तित करें (ए 65 है, बी 66 है) - E
  6. इसे प्रिंट करें - E

मेरे सर्वनाम वह / उसके हैं


बहुत चालाक, अच्छी तरह से किया
kos

@ धन्यवाद धन्यवाद :) मुझे संदेह है कि यह ओपी के लिए काम करेगा क्योंकि उसकी रेंज शायद वह नहीं है जो उसने पोस्ट किया है। मुझे उम्मीद है कि वे सादगी के लिए हैं।
टिम

5

और यहाँ मेरा awk संस्करण है:

awk '{
  if($_ <= 100 && $_ >= 0) {
      sub(/^([0-9]|[1-5][0-9])$/, "F", $_);
      sub(/^(6[0-9])$/, "D", $_);
      sub(/^(7[0-9])$/, "C", $_);
      sub(/^(8[0-9])$/, "B", $_);
      sub(/^(9[0-9]|100)$/, "A", $_);
      print
    }
    else {
      print "Only numbers between 0..100"
    }
}' -

या वन-लाइनर के रूप में:

awk '{if($_ <= 100 && $_ >= 0) { sub(/^([0-9]|[1-5][0-9])$/, "F", $_); sub(/^(6[0-9])$/, "D", $_); sub(/^(7[0-9])$/, "C", $_); sub(/^(8[0-9])$/, "B", $_);sub(/^(9[0-9]|100)$/, "A", $_);   print} else { print "Only numbers between 0..100"}}' -

4

यहाँ एक और "गूढ़" उत्तर है

perl -E '
    print "number: "; 
    $n = <>; 
    say qw/A A B C D E F F F F F/[11-($n+1)/10]
       if $n=~/^\s*\d/ and 0<=$n and $n<=100
'

व्याख्या

  • perl -E: -Eजैसे -e, स्क्रिप्ट को कमांड लाइन तर्क के रूप में पारित करने की अनुमति देता है। यह पर्ल वन-लाइनर्स चलाने का एक तरीका है। इसके विपरीत -e, -Eसभी वैकल्पिक सुविधाओं को सक्षम करता है (जैसे कि say, जो मूल रूप printसे एक अनुगामी न्यूलाइन के साथ है।)।
  • print "number: "; : नंबर दर्ज करने के लिए उपयोगकर्ता को संकेत दें।
  • $n = <>;: उस नंबर को सेव करें $n

अगले बिट को थोड़ा नीचे तोड़ने की जरूरत है। व्हॉट्सएप पर qw/string/तोड़कर बनाई गई सूची का मूल्यांकन करता है string। तो, qw/A A B C D E F F F F F/वास्तव में यह सूची है:

0 : A
1 : A
2 : B
3 : C
4 : D
5 : E
6 : F
7 : F
8 : F
9 : F
10 : F

इसलिए, say qw/A A B C D E F F F F F/[11-($n+1)/10]के बराबर है

my @F=("A","A","B","C","D","E","F","F","F","F","F");
print "$F[11-($n+1)/10]\n"

अब, पर्ल सरणी के अंत से गिनती करने वाले तत्वों को पुनः प्राप्त करने के लिए नकारात्मक सूचकांकों का उपयोग करने की अनुमति देता है। उदाहरण के लिए, $arrray[-1]सरणी के अंतिम तत्व को प्रिंट करेगा। इसके अलावा, फ्लोटिंग पॉइंट एरे इंडेक्स (उदाहरण 10.7) स्वचालित रूप से अगले निचले पूर्णांक (10.7, या 10.3 या जो भी सभी 10. बन जाते हैं) को काट दिया जाता है।

इस सब का नतीजा यह है कि सूचकांक 11-($n+1)/10हमेशा सरणी के उपयुक्त तत्व (ग्रेड) का मूल्यांकन करता है।


4
गूढ़ उत्तर सभी अच्छे हैं, लेकिन एक स्पष्टीकरण शामिल करें।
मूरू

1

यद्यपि आपने एक बैश समाधान के लिए कहा था, मुझे लगता है कि अजगर में, यह एक सुरुचिपूर्ण तरीके से किया जा सकता है। गलत इनपुट के मामले में दोनों हैंडलिंग त्रुटियों को कवर करना और 0 से 100 के बीच संख्या का "रूपांतरण" ए से एफ तक पत्र (या किसी अन्य) में:

#!/usr/bin/env python3
try:
    n = int(input("number: ")); n = n if n>0 else ""
    print("FEDCBA"[[n>=f for f in [50,60,70,80,90,101]].count(True)])
except:
    print("invalid input")

व्याख्या

  1. पहले हमें उपयोगकर्ता से नंबर प्राप्त करना होगा:

    n = int(input("number: "))
  2. हम कई स्थितियों के लिए मान्य होने के लिए इस संख्या का परीक्षण करते हैं:

    n>=50, n>=60, n>=70, n>=80, n>=90

    इनमें से प्रत्येक परीक्षण के लिए, परिणाम Falseया तो होगा True। इसलिए (कोड को थोड़ा संपीड़ित करना):

    [n>=f for f in [50,60,70,80,90]].count(True)]

    से एक आंकड़ा उत्पादन करेगा 0करने के लिए5

  3. इसके बाद, हम इस आंकड़े को एक स्ट्रिंग के लिए एक सूचकांक के रूप में उपयोग कर सकते हैं , एक चरित्र को आउटपुट के रूप में बनाने के लिए, उदाहरण के लिए

    "ABCDEF"[3] 

    आउटपुट "डी" (पहले चरित्र के बाद से = "ए")

  4. 101सूची में अतिरिक्त संख्या उत्पन्न होने की स्थिति में (इंडेक्स-) त्रुटि उत्पन्न करना है 100, क्योंकि "ABCDEF"[6]मौजूद नहीं है। उसी के लिए जाता है n = n if n>=0 else "", जो एक (मान-) त्रुटि पैदा करेगा यदि 0 से नीचे की संख्या दर्ज की
    गई है तो उन मामलों में, साथ ही अगर इनपुट एक आंकड़ा नहीं है, तो परिणाम होगा:

    invalid input

जाँच:

number: 10
F

number: 50
E

number: 60
D

number: 70
C

number: 80
B

number: 90
A

number: 110
invalid input

number: -10
invalid input

number: Monkey
invalid input
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.