답변:
보시다시피,이 문제는 적당히 길고 다소 반복적이지만 읽기 쉬운 솔루션 ( 터돈 과 AB의 bash 답변)뿐만 아니라 매우 짧지 만 직관적이지 않고 자체 문서화가 적은 솔루션 (Tim의 파이썬)을 인정합니다 그리고 bash 답변과 glenn jackman의 perl answer ). 이 모든 접근 방식은 가치가 있습니다.
컴팩트 성과 가독성 사이의 연속체 중간에있는 코드를 사용하여이 문제를 해결할 수도 있습니다. 이 접근 방식은 더 긴 솔루션만큼 읽을 수 있으며 작고 난해한 솔루션에 더 가까운 길이입니다.
#!/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 솔루션에는 가독성을 높이기 위해 빈 줄이 포함되었지만 더 짧게 원하면 제거 할 수 있습니다.
빈 줄이보다 실제로 약간 짧은 포함 소형으로, 여전히 꽤 읽을 변형 의 AB의 bash는 솔루션 . 이 방법에 비해 주요 장점은 다음과 같습니다.
(( ))작동 방식 에 대한 설명은 아래 참조 ).이 방법은 구성 자릿수를 수동으로 검사하지 않고 사용자 입력을 숫자 데이터로 사용하기 때문에 이러한 세 가지 장점이 모두 발생합니다.
-e해석하지 않도록 합니다. 이 스크립트는 기능이 풍부한 솔루션이 아니며 (세부 사항은 아래 참조), 유용한 기능으로 인해 두 글자 만 길어집니다. 사용자 가 이스케이프 처리 를해야한다는 것을 모르면 항상 with를 사용 하는 것이 좋습니다 .\-r-rread\q나 Q, 종료합니다.declare -A)을 만듭니다 . 각 문자 등급과 관련된 가장 높은 숫자 등급으로 채 웁니다.(( ))변수 이름을로 확장 할 필요가 없습니다 $. 대부분의 다른 상황에서 변수 이름 대신 변수 값을 사용 하려면이 작업을 수행해야합니다 .&&)를 사용합니다 .ifthen게시 된 다른 짧은 솔루션 과 마찬가지로 해당 스크립트는 숫자라고 가정하기 전에 입력을 확인하지 않습니다. 산술 평가 ( (( )))는 앞뒤 공백을 자동으로 제거하므로 문제 가 되지 않지만 다음과 같습니다.
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 과 함께 사용 했습니다 . 나는 그렇게 (그리고 어떻게) 그렇게 할 수 있는지 보여주기 위해 그렇게했습니다. 글롭과 정규 표현식은 텍스트와 일치하는 패턴을 지정하는 두 가지 방법이며,이 방법 중 어느 것이나 좋습니다.[[=~ 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 2bash를 찾아 두 번째 루프를 계속 진행합니다.
case글로브가있는 레이블AB의 bash answer 에서와 같이 숫자가 case어떤 문자 등급 상자에 속 하는지 알아내는 데 사용하지 않습니다 . 그러나 사용자의 입력을 고려해야하는지 결정하는 데 사용합니다.case
*( )@([1-9]*([0-9])|+(0))*( )*( )[qQ]?([uU][iI][tT])*( )*이것은 껍질 globs 입니다.
)어떤 개구와 일치되지 않도록 (하고, case이 비교 될 때 실행되는 명령의 패턴을 분리의 구문.;;는 case특정 사례 일치를 위해 실행할 명령의 끝을 나타내는 구문입니다 (그리고 실행 후 후속 사례는 테스트하지 않아야 함).일반 쉘 글 로빙은 *0 개 이상의 문자 ?를 일치시키고 정확히 하나의 문자를 일치 시키며 [ ]괄호 안의 문자 클래스 / 범위를 제공 합니다. 그러나 확장 된 globbing을 사용 하고 있습니다. bash대화식 으로 사용할 때는 기본적으로 확장 글 로빙이 활성화 되지만 스크립트를 실행할 때는 기본적으로 비활성화됩니다. shopt -s extglob스크립트 맨 위에 있는 명령이 켜집니다.
*( )@([1-9]*([0-9])|+(0))*( )숫자 입력을 확인 하는 다음 시퀀스와 일치합니다.
*( )) *( )구조 경기는 0 개 단지 공간 여기에 괄호 안의 패턴의 더. -e을 read활성화 하는 플래그로 작성되었으므로 걱정하지 않아도 됩니다. 이것은 사용자가 왼쪽 및 오른쪽 화살표 키를 사용하여 텍스트에서 앞뒤로 이동할 수 있도록하지만 일반적으로 탭이 문자 그대로 입력되지 못하게하는 부작용이 있습니다.@( )) 하나의 ( |)
[1-9]) 다음에 *( )임의의 숫자 ( [0-9]) 중 0 이상 ( ).+( ))입니다 0.*( )다시 0 개 이상의 공백 ( )*( )[qQ]?([uU][iI][tT])*( )quit 명령을 확인 하는 다음 시퀀스와 일치합니다.
*( ))q또는 Q( [qQ]).?( )) :
u또는 U( [uU]) 다음에 i또는 I( [iI]) 다음에 t또는 T( [tT]).*( )다시 0 개 이상의 공백 ( )쉘 글로브가 아닌 정규 표현식에 대해 사용자 입력을 테스트하려는 경우이 버전을 사용하는 것이 좋습니다.이 버전은 동일한 방식으로 작동하지만 확장 글 로빙 대신 및 terdon 's answer 에서 [[와 =~같이 사용합니다 .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명령이 버전에서 사용되지 로빙 생략한다.
정규 표현 기술은 bash의 extglobs에 능숙합니다.
=~연산자 의 오른쪽에 지정된 패턴은 정규 표현식의 작동 방식입니다.
^\ *([1-9][0-9]*|0+)\ *$숫자 입력을 확인 하는 다음 시퀀스와 일치합니다.
^) ( ).*, 적용된 접미사) 공백. 보통 \정규 표현식에서 공백을 이스케이프 처리 할 필요는 없지만 [[구문 오류를 방지하기 위해 필요 합니다.( )) 즉, 하나 또는 다른 ( |의) :
[1-9][0-9]*: 0이 아닌 숫자 ( [1-9]) 다음에 *임의의 숫자 ( [0-9]) 의 0 이상 ( 적용된 후위 ).0+:의 하나 이상 ( +, 적용된 접미사) 0.\ *이전과 같이 0 개 이상의 공백 ( )$).case테스트중인 전체 표현식과 일치하는 레이블 과 달리 =~왼쪽 표현식의 일부가 오른쪽 표현식으로 제공된 패턴과 일치하면 true를 리턴합니다. 왜 '입니다 ^및 $앵커, 라인의 시작과 끝을 지정, 여기에 필요하고 함께 방법에서 나타나는 아무것도 문법적으로 일치하지 않는 case및 extglobs.
괄호는 할 필요 ^와 $의 분리에 결합 [1-9][0-9]*하고 0+. 그렇지 않으면의 분리 것 ^[1-9][0-9]*하고 0+$, 그리고 제로가 아닌 숫자로 시작하는 모든 입력을 일치 또는 로 끝나는 0(또는 정지 사이에 비 숫자를 포함 할 수있는 모두).
^\ *q(uit)?\ *$quit 명령을 확인 하는 다음 시퀀스와 일치합니다.
^).\ *위의 설명 참조)q. 또는가 활성화되어 Q있기 때문 shopt nocasematch입니다.?부분 문자열 ( ( )) 의 0 번 또는 1 번 (postfix ) ) :
u, 뒤에 i, 뒤에 t. 또는 shopt nocasematch활성화되어 u있기 때문에 U; 독립적 i으로 I; 그리고 독립적으로, 일 t수있다 T. (즉, 가능성은 및로 제한 되지 않습니다 .)uitUIT\ *).$).이미 기본 아이디어가 있습니다. 이것을 코딩하려면 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
-ge사용하고 있기 때문에 이러한 테스트를 제거 할 수 있습니다 elif. 그리고 사랑이 (( $response < X ))없나요?
(( $response < X )), 그러나 나는 이것을 더 명확하게 생각하고 OP는 분명히 bash 스크립팅에 새로운 것입니다.
#!/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
[0-59], 0,1,2,3,4,5 또는 9 등의 문자를 의미합니다. 숫자 값에 어떻게 작동하는지 알 수 없습니다 .
모든 우분투 설치에는 파이썬이 있으므로 파이썬 스크립트 하나의 라이너가 있습니다. bash에 있어야하는 경우 쉘 스크립트로 동등한 것을 작성했습니다 .
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.내 대명사는
input()전화를 걸고 대신 eval()사용 raw_input()하십시오. 또한 성적 90+을 인쇄 할 때 등급이 맞지 않습니다 . B사용 chr(74 - max(4, num))....
input()에 raw_input()python2..thats에 대한이 ...
print chr(75-max(5,int('0'+raw_input('Enter the number: ')[:-1])))
python3가 없습니다 raw_input()내가 제안 ... raw_input()당신이 사용하여 실행 말한대로 초기 하나 python2..
다음 은 배열에 101 개의 항목을 채우고 사용자 입력을 검사하는 반- 비밀 bash 솔루션입니다. 실제 사용에도 합리적입니다. 우수한 성능이 필요한 경우 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.quitqQ .단점 :
g). ). 오래된 말로 "버그가 아니라 기능입니다!" 아마도 요멋지다, 응? (그래요.)
p함수 (P)은 수치 인덱스 배열 opulates g의 g의 세 번째 인수로 주어진 (문자) 값과 두 번째 행의 첫번째 인수에 이르기까지의 인덱스 라 데스를.p 숫자 범위를 정의하기 위해 각 문자 등급에 대해 호출됩니다.q거나 (또는 Q)로 시작하지 않고 g문자 등급이 입력 된 숫자에 해당하는 배열을 확인하고 해당 문자를 인쇄하십시오.[[ $n =~ ^(0|[1-9]+[0-9]*)$ ]]
Python 2에서 만든 후 bash로 만들기로 결정했습니다.
#! /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.내 대명사는
그리고 여기 내 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"}}' -
또 다른 "비평"답변이 있습니다.
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"
이제 Perl은 음수 인덱스를 사용하여 배열 끝에서 계산 된 요소를 검색 할 수 있습니다. 예를 들어$arrray[-1] 배열의 마지막 요소를 인쇄합니다. 또한 부동 소수점 배열 인덱스 (예 : 10.7)는 다음으로 낮은 정수 (10.7 또는 10.3 또는 10이되는 모든 것)로 자동으로 잘립니다.
이 모든 결과는 인덱스가 11-($n+1)/10항상 배열의 적절한 요소 (그레이드)로 평가된다는 것입니다.
bash 솔루션을 요청했지만 파이썬에서는 간단하게 우아하게 수행 할 수 있다고 생각합니다. 입력이 잘못되었을 때의 처리 오류와 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")
먼저 사용자로부터 번호를 얻어야합니다.
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"를 출력합니다 (첫 문자 = "A"이므로)
101목록에 추가 된 것은 존재하지 않기 100때문에 숫자가을 초과하는 경우 (Index-) 오류를 생성하는 것 "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