Я хочу сделать сценарий, который будет запрашивать у вас число от 0 до 100, а затем давать вам оценку на основе числа.
Я бы хотел это в bash.
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
Как Вы видели, эта проблема признается в решениях, которые являются умеренно долгими и несколько повторяющимися, но очень читаемыми (terdon's и ответы удара A.B.'s), а также тех, которые являются очень короткими, но необладающими интуицией и намного меньше самодокументирования (Python Tim, и колотите ответы и ответ жемчуга glenn jackman). Все эти подходы ценны.
Можно также решить эту проблему с кодом посреди континуума между компактностью и удобочитаемостью. Этот подход почти так же читаем как более длительные решения с длиной ближе к небольшим, тайным решениям.
#!/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."
В этом решении для удара я включал некоторые пустые строки для улучшения удобочитаемости, но Вы могли удалить их, если бы Вы хотели это еще короче.
Пустые строки включали, это на самом деле незначительно короче, чем compactified, все еще довольно читаемый вариант решения для удара A.B.'s. Его основные преимущества перед тем методом:
((
))
работы).Все три из этих преимуществ возникают, потому что этот метод использует вход пользователя в качестве числовых данных, а не путем ручного исследования его составляющих цифр.
-e
) и не интерпретируйте \
как символ ESC (-r
).-r
с read
, если Вы не знаете, что необходимо позволить пользователю предоставить \
Escape.q
или Q
, выход.declare -A
). Заполните его с самым высоким числовым классом, связанным с каждой буквенной оценкой.((
))
арифметическая оценка, имена переменной не должны быть расширены с $
. (В большинстве других ситуаций, если Вы хотите использовать значение переменной вместо его имени, необходимо сделать это.)&&
) вместо if
-then
.Как другие короткие отправленные решения, тот сценарий не проверяет вход прежде, чем предположить, что это - число. Арифметическая оценка (((
))
) автоматически ведущий и запаздывающий пробел полос, таким образом, это не проблема, но:
0
интерпретируется как являющийся в восьмеричном. Например, сценарий скажет, что Вы 77 являетесь C, в то время как 077 D. Хотя некоторые пользователи могут хотеть это, по всей вероятности не делайте и это может вызвать беспорядок.По тем причинам можно хотеть использовать что-то вроде этого расширенный сценарий, который проверяет, чтобы гарантировать, что вход хорош, и включает некоторые другие улучшения.
#!/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
с расширенным globbing вместо [[
с =~
оператор соответствия регулярного выражения (как в ответе terdon). Я сделал это, чтобы показать, что (и как) это может также быть сделано тот путь. Шарики и regexps являются двумя способами указать шаблоны, которые соответствуют тексту, и любой метод хорошо для этого приложения.cutoffs
массив). Это запрашивает числа и дает соответствующие буквенные оценки, пока терминальный вход доступен, и пользователь не сказал этому выходить. Оценка по do
...done
вокруг кода в Вашем вопросе похоже на желание этого.q
или quit
.Этот сценарий использует несколько конструкций, которые могут быть незнакомыми новичкам; они детализированы ниже.
continue
Когда я хочу перескочить через остальную часть тела внешнего while
цикл, я использую continue
команда. Это возвращает его до вершины цикла, чтобы считать более вход и выполнить другое повторение.
В первый раз, когда я делаю это, единственный цикл, в котором я нахожусь, является внешним while
цикл, таким образом, я могу звонить continue
без аргумента. (Я нахожусь в a 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
выяснять, какое мусорное ведро буквенной оценки число падает в (как в ответе удара A.B.'s). Но я действительно использую case
чтобы решить, нужно ли вход пользователя рассмотреть:
*( )@([1-9]*([0-9])|+(0))*( )
*( )[qQ]?([uU][iI][tT])*( )
*
Это шарики оболочки.
)
это не подобрано никаким открытием (
, который является case
синтаксис для разделения шаблона от команд, которые работают, когда это подобрано.;;
case
синтаксис для указания на конец команд для выполнения за особым соответствием случая (и что никакие последующие случаи не должны быть протестированы после выполнения их).Обычная оболочка globbing обеспечивает *
соответствовать нулю или большему количеству символов, ?
соответствовать точно одному символу и символьным классам/диапазонам в [
]
скобки. Но я использую расширенный globbing, который идет кроме того. Расширенный globbing включен по умолчанию при использовании bash
в интерактивном режиме, но отключен по умолчанию при запущении скрипта. shopt -s extglob
команда наверху сценария включает его.
*( )@([1-9]*([0-9])|+(0))*( )
, то, которое проверяет на числовой вход, соответствует последовательности:
*( )
). *(
)
создайте нуль соответствий или больше шаблона в круглых скобках, которые вот просто пространство.-e
флаг к read
включает GNU readline. Это - так пользователь, может двинуться вперед-назад в их тексте с левыми и правыми клавишами со стрелками, но он имеет побочный эффект общего препятствования тому, чтобы вкладки были введены буквально.@(
)
) из любого (|
): [1-9]
) сопровождаемый нулем или больше (*(
)
) из любой цифры ([0-9]
).+(
)
) из 0
.*( )
), снова.*( )[qQ]?([uU][iI][tT])*( )
, то, которое проверяет на команду выхода, соответствует последовательности:
*( )
).q
или Q
([qQ]
).?(
)
)-: u
или U
([uU]
) сопровождаемый i
или I
([iI]
) сопровождаемый t
или T
([tT]
).*( )
), снова.Если Вы предпочитаете тестировать вход пользователя против регулярного выражения, а не шарика оболочки, Вы могли бы предпочесть использовать эту версию, которая работает то же, но использование [[
и =~
(как в ответе terdon) вместо case
и расширенный globbing.
#!/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
команда опущена, поскольку globbing не используется в этой версии.
Навыки регулярного выражения более распространены, чем мастерство в extglobs удара.
Что касается шаблонов, указанных направо от =~
оператор, вот то, как те регулярные выражения работают.
^\ *([1-9][0-9]*|0+)\ *$
, то, которое проверяет на числовой вход, соответствует последовательности:
^
).*
, прикладной постфикс) пробелы. Пространство не должно обычно быть \
- оставленный в регулярном выражении, но это необходимо с [[
предотвратить синтаксическую ошибку.(
)
) это один или другой (|
) из: [1-9][0-9]*
: ненулевая цифра ([1-9]
) сопровождаемый нулем или больше (*
, прикладной постфикс) любой цифры ([0-9]
).0+
: один или несколько (+
, прикладной постфикс) 0
.\ *
), как прежде.$
).В отличие от этого, case
маркировки, которые соответствуют против целого протестированного выражения, =~
возвращает true, если какая-либо часть его левого выражения соответствует шаблону, данному как его правое выражение. Это то, почему ^
и $
привязки, указывая начало и конец строки, необходимы здесь и не соответствуют синтаксически ничему появляющемуся в методе с case
и extglobs.
Круглые скобки необходимы для создания ^
и $
свяжите с разъединением [1-9][0-9]*
и 0+
. Иначе это было бы разъединение ^[1-9][0-9]*
и 0+$
, и соответствуйте любому входу, запускающемуся с ненулевой цифры или заканчивающемуся a 0
(или оба, которые могли бы все еще включать промежуточные нецифры).
^\ *q(uit)?\ *$
, то, которое проверяет на команду выхода, соответствует последовательности:
^
).\ *
, посмотрите выше объяснения).q
. Или Q
, с тех пор shopt nocasematch
включен.?
) - подстроки ((
)
): u
, сопровождаемый i
, сопровождаемый t
. Или, с тех пор shopt nocasematch
включен u
может быть U
; независимо, i
может быть I
; и независимо, t
может быть T
. (Таким образом, возможности не ограничены uit
и UIT
.)\ *
).$
). Вы уже имеете общее представление. Если Вы хотите кодировать это в bash
(который является разумным выбором, так как это - оболочка по умолчанию на Ubuntu и большинстве других Linux), Вы не можете использовать 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
#!/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
и более компактная версия (Спасибо @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
Все установки Ubuntu имеют Python, таким образом, вот является Python сценарием один лайнер. Если Вам нужен он, чтобы быть в ударе, я имею также записанный эквивалент как сценарий оболочки .
print (chr(75-max(5,int('0'+raw_input('Enter the number: ')[:-1]))))
, Чтобы выполнить, сохранить его в файле (например, grade.py
) и затем выполнить его в терминале с этим:
python grade.py
Это - то, что Вы будете видеть:
Enter the number: 65
E
, Как это работает?
65
. 065
. 06
. 70
. E
. E
. После создание его в 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
, Как это работает?
65
. 065
(и эти 10#
сохраняет его, базируются 10). 06
. 70
. E
. E
. Вот другой "тайный" ответ
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
, который является в основном a 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
всегда оценивает к соответствующему элементу (класс) массива.
Хотя Вы попросили решение для удара, я думаю в Python, это может быть сделано в изящном короткий путь. Покрытие обеих ошибок из-за неправильного обращения в случае неправильного входа и "преобразования" числа между 0 и 100 в буквы от до 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")
Сначала мы должны получить число от пользователя:
n = int(input("number: "))
Мы тестируем это число, чтобы быть допустимыми для многих условий:
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
Впоследствии, мы можем использовать это число в качестве индекса для строки, для создания символа, как произведено, например.
"ABCDEF"[3]
произведет "D" (начиная с первого символа =)
Дополнительное 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
Вот мое полутайное решение для удара, которое заполняет массив с 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
одномерный индексный массив). Как говорится, "Это не ошибка, это - функция!" Ну, Возможно.Довольно прохладный, ха? (Ну, я думаю так.)
p
функция заполняет численно индексный массив g
из классов, в индексах в пределах от его первого аргумента его секунде, с (буква) значение, данное в его третьем аргументе.p
назван для каждой буквенной оценки, для определения ее числового диапазона.q
(или Q
), проверка g
массив, для которого буквенная оценка соответствует номеру, введенному, и печать та буква.dpkg
команды, они должны смонтироваться к LiveCD procfs, tmpfs, и т.д. Here' s, в конце абзаца , примере команд монтирования. Я на самом деле думаю, переустанавливание ядра было бы достаточно.
– Hi-Angel
9 August 2016 в 06:03
И вот моя 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"}}' -