Як написати скрипт оболонки, щоб призначити оцінки літер числовим діапазонам?


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

Стислість проти читабельності: середина

Як ви вже бачили, це завдання допускає до рішень, які помірно довгі і кілька повторюваних , але дуже читається ( terdon - х і AB в Баш відповіді), а також ті , які є дуже короткими , але не інтуїтивно і набагато менш самодокументірован (Тіма пітон і Баш відповіді і Glenn Джекмана Perl відповідь ). Всі ці підходи цінні.

Ви також можете вирішити цю проблему за допомогою коду в середині континууму між компактністю та читабельністю. Цей підхід є майже таким же читабельним, як і більш довгі рішення, з довжиною ближче до малих езотеричних рішень.

#!/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."

У це рішення bash я включив кілька порожніх рядків для підвищення читабельності, але ви можете їх видалити, якби хотіли ще коротше.

Порожні рядки включені, це насправді лише трохи коротше компактифицированного, все ще досить читається варіант з розчину Баша АБ . Основними його перевагами перед цим методом є:

  • Це більш інтуїтивно зрозуміло.
  • Простіше змінити межі між оцінками (або додати додаткові оцінки).
  • Він автоматично приймає вхід з провідними та кінцевими пробілами (див. Нижче для пояснення того, як (( ))працює).

Усі ці три переваги виникають тому, що цей метод використовує введення користувача як числові дані, а не вручну вивчаючи його складові цифри.

Як це працює

  1. Прочитайте вхід від користувача. Нехай вони використовують клавіші зі стрілками для переміщення в тексті, який вони ввели ( -e), а не інтерпретують \як символ втечі ( -r).
    Цей скрипт не є багатофункціональним рішенням - див. Нижче для уточнення - але ці корисні функції роблять його на два символи довше. Я рекомендую завжди використовувати -rз read, якщо ви не знаєте , що вам потрібно , щоб дозволити користувачеві харчування \пагонів.
  2. Якщо користувач написав qабо Q, вийдіть.
  3. Створіть асоціативний масив ( declare -A). Населяйте його найвищим числовим класом, пов’язаним із кожним класом букви.
  4. Проведіть курси через літери від найнижчих до найвищих, перевіряючи, чи вказане користувачем число є достатньо низьким, щоб потрапити в числовий діапазон кожної літери.
    За допомогою (( ))арифметичного оцінювання імена змінних не потрібно розширювати $. (У більшості інших ситуацій, якщо ви хочете використовувати значення змінної замість її імені, ви повинні зробити це .)
  5. Якщо він потрапляє в діапазон, роздрукуйте оцінку та вийдіть .
    Для стислості я використовую коротке замикання та оператор ( &&), а не if- then.
  6. Якщо цикл закінчується, і діапазон не збігається, припустіть, що введене число є занадто високим (понад 100) і повідомте користувачеві, що він був поза діапазоном.

Як це поводиться, із дивним входом

Як і інші опубліковані короткі рішення, цей скрипт не перевіряє вхід, перш ніж вважати, що це число. Арифметичне оцінювання ( (( ))) автоматично знімає пробіли та пробіли, тому це не проблема, але:

  • Введення, яке зовсім не схоже на число, інтерпретується як 0.
  • З введенням, яке виглядає як число (тобто, якщо воно починається з цифри), але містить недійсні символи, сценарій видає помилки.
  • Мульти-значний вхід починаючи з 0буде інтерпретуватися як в вісімковій системі . Наприклад, сценарій скаже вам, що 77 - це C, а 077 - D. Хоча деякі користувачі можуть цього хотіти, швидше за все, це не може, і це може спричинити плутанину.
  • З боку плюс, якщо йому дано арифметичний вираз, цей скрипт автоматично спрощує його і визначає пов'язаний з ним літер. Наприклад, він скаже вам, що 320/4 - це B.

Розширена, повністю представлена ​​версія

З цих причин ви можете використовувати щось на кшталт цього розширеного сценарію, який перевіряє, чи є вхід хорошим, і включає деякі інші вдосконалення.

#!/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

Це все ще досить компактне рішення.

Які функції додає це?

Ключові моменти цього розширеного сценарію:

  • Перевірка вводу сценарій terdon перевіряє вхід за допомогоюif [[ ! $response =~ ^[0-9]*$ ]] ... , так що я покажу ще один спосіб, який жертвує стислість , але є більш надійним, дозволяючи користувачеві ввести початкові і кінцеві пробіли і відмовляючи вираз , яке може або не може бути призначений як восьмеричні (якщо це не нуль) .
  • Я використовував caseз розширеною підстановкою замість [[з =~ регулярними виразами оператора (як в відповіді terdon в ). Я зробив це, щоб показати, що (і як) це також можна зробити так. Глобуси та регулярні виразки - це два способи визначення шаблонів, що відповідають тексту, і будь-який метод чудово підходить для цієї програми.
  • Як і сценарій bash AB , я все це уклав у зовнішній цикл (за винятком початкового створення 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для пошуку bash і замість цього продовжую другу петлю.

Пояснення: caseМітки з глобусами

Я не використовую , caseщоб з'ясувати , яка буква класу бен число потрапляє (як в Баш відповідь АБ ). Але я використовую, caseщоб вирішити, чи слід враховувати дані користувача:

  • дійсне число, *( )@([1-9]*([0-9])|+(0))*( )
  • команда вийти, *( )[qQ]?([uU][iI][tT])*( )
  • що-небудь інше (і, таким чином, недійсне введення), *

Це черепашки .

  • Кожен супроводжується тим, )що не відповідає жодному отвору (, який єcase синтаксисом для відокремлення шаблону від команд, які виконуються при його зіставленні.
  • ;;- це caseсинтаксис для вказівки кінця команд для запуску патикулярного відповідника (і що після їх запуску не слід перевіряти наступні випадки).

Звичайна глобальна оболонка оболонки забезпечує узгодження *нуля або більше символів, ?відповідність точно одному символу та класи / діапазони символів у [ ]дужках. Але я використовую розширений глобус , що виходить за рамки цього. Розширений глобул увімкнено за замовчуванням при bashінтерактивному використанні , але відключений за замовчуванням під час запуску сценарію. shopt -s extglobКоманди у верхній частині сценарію перетворює його.

Пояснення: розширене глобування

*( )@([1-9]*([0-9])|+(0))*( ), що перевіряє чисельний ввід , відповідає послідовності:

  • Нульовий або більше пробілів ( *( )). У *( )конструкт відповідає нулю або більше шаблону в дужках, що тут є тільки простір.
    Насправді існує два види горизонтального простору, пробіли та вкладки, і часто бажано також відповідати вкладкам. Але я не турбуюся про це тут, тому що цей сценарій написаний для ручного, інтерактивного введення, а -eпрапор readдозволяє включити читання GNU. Це так, що користувач може рухатись вперед та назад у тексті за допомогою клавіш зі стрілками вліво та вправо, але це побічний ефект, як правило, запобігає буквальному введенню вкладок.
  • Одне виникнення ( @( )) будь-якого ( |):
    • Ненульова цифра ( [1-9]) з наступним нулем або більше ( *( )) будь-якої цифри ( [0-9]).
    • Один або більше ( +( )) з 0.
  • Нуль або більше пробілів ( *( )), знову.

*( )[qQ]?([uU][iI][tT])*( ), яка перевіряє команду quit , відповідає послідовності:

  • Нульовий або більше пробілів ( *( )).
  • qабо Q( [qQ]).
  • Необов'язково - тобто нуль або один вхід ( ?( )) - з:
    • uабо U( [uU]), за яким слідує iабо I( [iI]), після tабо T( [tT]).
  • Нуль або більше пробілів ( *( )), знову.

Варіант: Підтвердження введення з розширеним регулярним виразом

Якщо ви віддаєте перевагу тестуванню вводу користувача на регулярний вираз, а не на оболонці, ви можете скористатися цією версією, яка працює так само, але використовує [[та =~(як у відповіді тердона ) замість 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

Можливими перевагами такого підходу є те, що:

  • У цьому конкретному випадку синтаксис трохи простіший, принаймні, у другому шаблоні, де я перевіряю на команду quit. Це тому, що мені вдалося встановити параметр 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і exglobs.

Дужки потрібні для створення ^та $прив’язки до диз'юнкції [1-9][0-9]*та 0+. В іншому випадку це було б диз'юнкцією ^[1-9][0-9]*та 0+$і збігом будь-якого вводу, починаючи з ненульової цифри або закінчуючи символом 0(або обом, що все ще може включати нецифрові цифри між ними).

^\ *q(uit)?\ *$, яка перевіряє команду quit , відповідає послідовності:

  • Початок рядка (^ ).
  • Нульовий або більше пробілів (\ * див. Пояснення вище).
  • Лист q. Або Q, оскількиshopt nocasematch це ввімкнено.
  • За бажанням - тобто нуль або один вхід (постфікс ?) - підрядка (( ) ):
    • u, а за iними - за ним t. Або, оскільки shopt nocasematchце ввімкнено uможе бути U; незалежно, iможе бути I; і незалежно, tможе бути T. (Тобто можливості не обмежуються uitі UIT.)
  • Знову чи більше пробілів ( \ *).
  • Кінець рядка ( $).

3
скажи мені правду .. скільки часу пройшло? ;)
heemayl

4
@heemayl Я не зовсім впевнений, оскільки писав це у багатьох маленьких частинах протягом дня (після цього було повне ознайомлення та редагування, безпосередньо перед публікацією). Я впевнений, що це закінчилося більше часу, ніж я б думав, коли почав, хоча б я думав про те, як довго це займе. :)
Елія Каган

6
пишіть все більше і більше, мені потрібна книга ваших відповідей.
Гріеш Чаухан

TL; DR, але змусив мене сміятися!
Fabby

все від назви до пояснення добре. Я зрозумів це в першу чергу, але прочитав його ще раз тому, що хотів
Сумет Дешмух

23

У вас вже є основна ідея. Якщо ви хочете зашифрувати це в bash(що є розумним вибором, оскільки це оболонка за замовчуванням для Ubuntu та більшості інших Linuxes), ви не можете використовувати, 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
@muru правда, спасибі Я застрягав, думаючи в діапазоні чисел, але причин для цього не було. Що стосується (( $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 тощо. Я не бачу, як це може працювати для числових значень.
steeldriver

3
Вам не потрібно постійно бути FGITW. Не витрачайте часу, пишіть хороші відповіді. Подивіться, як працюють тердон або Елія Каган.
муру

@AB Я помітив, що це рішення можна скоротити, в основному за допомогою стилістичних змін, при цьому залишаючись досить читабельним. Стислість рідко є найважливішою увагою, тому я не думаю, що слід змінювати те, що у вас є, таким чином. Але оскільки більш компактна форма не займає багато місця, ви можете розглянути і її показ, якщо деякі читачі захочуть коротший сценарій, що працює так само. (Якщо вам подобається, будь ласка, не забудьте скористатися моєю скороченою версією чи будь-яким варіантом на ній.)
Eliah Kagan

9

Усі установки Ubuntu мають Python, тому ось сценарій python - один вкладиш. Якщо вам потрібно, щоб це було в bash, я також написав еквівалент як сценарій оболонки .

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
AB

Не використовуйте input(), він зателефонує eval(), використовуйте raw_input()замість цього, тому що ваша класифікація не є правильною, як 90+і друк класу B.. використовуйте chr(74 - max(4, num))....
heemayl

добре .. ваше рішення добре, і він буде працювати в python2 також .. просто змінити на input()на raw_input()python2..це це ..
heemayl

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

Тоді вам також потрібно змінити свій вихідний код. Ваш модифікований код, оскільки він наразі стоїть, є неправильним, хоча, як python3немає, raw_input()я запропонував raw_input()для вашого початкового, як ви сказали, запустити його за допомогою python2..
heemayl

6

Ось мій підлозі -esoteric розчин Баш, який заповнює масив з 101 записів , а потім перевіряє введення користувача по відношенню до ним. Навіть для використання в реальному житті це розумно - якщо вам потрібна відмінна продуктивність, ви б не використовували bash, і сто (або близько того) завдань все ще швидко. Але це перестане бути розумним, якби його поширити на значно більший діапазон (наприклад, мільйон).

#!/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.
  • Списки вищих класів спочатку, щоб допомогти вам мислити позитивно. :)
  • Гм, це робить цю роботу, має сенс навіть після того, як ви подивитесь на це, і має суттєві особливості. Ви насправді можете використати це!

Недоліки:

  • Це дає вам F, коли ви вводите нечислове введення ... але це не дуже погано, чи не так? Якщо ви дасте не номер, де потрібне число, можливо, ви заслужили F!
  • Неоднозначне, можливо восьмеричне введення, трактується як восьмерочне (оскільки g є одновимірним індексованим масивом ). Як говорить стара приказка: "Це не помилка, це особливість!" Ну, можливо.
  • Введення, яке знаходиться поза діапазоном або не має числа, призводить до друку порожнього рядка. З цим, правда, немає нічого поганого: він говорить вам, який клас букви відповідає вашому вводу, а для неправильного введення - немає.
  • Поставте від’ємне число, і це… ну, назвіть його великоднім яйцем .
  • Все ще значно довше, ніж рішення пітону Тіма . Так, я не можу реально розкрутити, що здається перевагою.

Якась крута, так? (Ну, я так думаю.)

Як це працює

  1. pФункція р opulates чисельно індексований масив gз г Rades, на індекси в діапазоні від першого аргументу до другого її, зі значенням (буква) , наведеної в його третім аргументом.
  2. p називається для кожного класу літер, щоб визначити його числовий діапазон.
  3. Продовжуйте читати введення користувача до тих пір, поки це доступно і не починається з q(або Q), перевіряючи gмасив, для якого ступінь букви відповідає введеному номеру, і друкуючи цей лист.

Що з цим умовним? [[ $n =~ ^(0|[1-9]+[0-9]*)$ ]]
Геліо

6

Після того, як зробити це в Python 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"

Щоб запустити, збережіть його у файлі (наприклад, grade.sh), зробіть його виконуваним chmod +x grade.shі потім запустіть./grade.sh .

Ось що ви побачите:

Enter the number: 65
E

Як це працює?

  1. Візьміть внесок - 65.
  2. Додайте 0 до початку - 06510# зберігає його основою 10).
  3. Видалити останній знак - 06.
  4. 75 відніміть це число - 70.
  5. Перетворити на букву (А - 65, В - 66) - E.
  6. Роздрукуйте - E.

Мої займенники - Він / Він


Дуже розумний, молодець
kos

@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: the -E, like -e, дозволяє передавати скрипт як аргумент командного рядка. Це спосіб запустити однорівники Perl. На відміну від цього -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"

Тепер Perl дозволяє використовувати негативні індекси для отримання елементів, рахуючи з кінця масиву. Наприклад,$arrray[-1] буде надрукувати останній елемент масиву. Крім того, індекси масиву з плаваючою комою (наприклад, 10.7) автоматично підрізаються до наступного нижнього цілого числа (10,7, або 10,3 або будь-якого іншого, що стає 10.)

Результатом всього цього є те, що індекс 11-($n+1)/10завжди оцінює відповідний елемент (клас) масиву.


4
Езотеричні відповіді - це все добре, але будь ласка, додайте пояснення.
муру

1

Хоча ви просили баш-рішення, я думаю, що в python це можна зробити елегантно коротко. Покриття обох помилок обробки у разі неправильного введення та "перетворення" числа між 0 і 100 в літери від A до F (або будь-які інші):

#!/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] 

    виведе "D" (оскільки перший символ = "A")

  4. До 101списку додатково входить помилка (Index-), якщо їх число перевищує 100, оскільки "ABCDEF"[6]його не існує. Те саме стосується n = n if n>=0 else "", що створить (Value-) помилку, якщо введено число нижче 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 та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.