문자 등급을 숫자 범위에 할당하는 쉘 스크립트를 작성하는 방법은 무엇입니까?


19

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

답변:


20

간결성 대 가독성 : 중간

보시다시피,이 문제는 적당히 길고 다소 반복적이지만 읽기 쉬운 솔루션 ( 터돈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는 솔루션 . 이 방법에 비해 주요 장점은 다음과 같습니다.

  • 더 직관적입니다.
  • 성적 사이의 경계를 변경하거나 성적을 추가하는 것이 더 쉽습니다.
  • 선행 및 후행 공백이있는 입력을 자동으로 승인합니다 ( (( ))작동 방식 에 대한 설명은 아래 참조 ).

이 방법은 구성 자릿수를 수동으로 검사하지 않고 사용자 입력을 숫자 데이터로 사용하기 때문에 이러한 세 가지 장점이 모두 발생합니다.

작동 원리

  1. 사용자의 입력을 읽습니다. 입력 한 텍스트에서 화살표 키를 사용하여 이동 하고 이스케이프 문자 ( ) 로 -e해석하지 않도록 합니다. 이 스크립트는 기능이 풍부한 솔루션이 아니며 (세부 사항은 아래 참조), 유용한 기능으로 인해 두 글자 만 길어집니다. 사용자 가 이스케이프 처리 를해야한다는 것을 모르면 항상 with를 사용 하는 것이 좋습니다 .\-r
    -rread\
  2. 사용자가 작성하는 경우 qQ, 종료합니다.
  3. 연관 배열 ( declare -A)을 만듭니다 . 각 문자 등급과 관련된 가장 높은 숫자 등급으로 채 웁니다.
  4. 문자 등급을 최저에서 최고로 반복하면서 사용자 제공 숫자가 각 등급의 숫자 범위에 해당 할 정도로 낮은 지 확인하십시오. 산술 평가를
    사용하면 (( ))변수 이름을로 확장 할 필요가 없습니다 $. 대부분의 다른 상황에서 변수 이름 대신 변수 값을 사용 하려면이 작업을 수행해야합니다 .
  5. 이 범위에 속하면 등급을 인쇄하고 종료하십시오 .
    간결하게 하기 위해 - 대신 단락 연산자 ( &&)를 사용합니다 .ifthen
  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의 스크립트는로 입력확인 하므로 다른 방법을 보여줍니다.이 방법은 간결성을 희생하지만 더 견고하여 사용자가 선행 및 후행 공백을 입력하고 8 진수로 의도되거나 그렇지 않을 수있는 표현식을 거부합니다 (0이 아닌 경우) .if [[ ! $response =~ ^[0-9]*$ ]] ...
  • 나는 terdon 's answer 에서 와 같이 정규 표현식 일치 연산자 대신 확장 globbingcase 과 함께 사용 했습니다 . 나는 그렇게 (그리고 어떻게) 그렇게 할 수 있는지 보여주기 위해 그렇게했습니다. 글롭과 정규 표현식은 텍스트와 일치하는 패턴을 지정하는 두 가지 방법이며,이 방법 중 어느 것이나 좋습니다.[[=~
  • AB의 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 2bash를 찾아 두 번째 루프를 계속 진행합니다.

설명 : case글로브가있는 레이블

AB의 bash answer 에서와 같이 숫자가 case어떤 문자 등급 상자에 속 하는지 알아내는 데 사용하지 않습니다 . 그러나 사용자의 입력을 고려해야하는지 결정하는 데 사용합니다.case

  • 유효한 숫자 *( )@([1-9]*([0-9])|+(0))*( )
  • quit 명령 *( )[qQ]?([uU][iI][tT])*( )
  • 다른 것 (따라서 잘못된 입력) *

이것은 껍질 globs 입니다.

  • 각각은 뒤에 )어떤 개구와 일치되지 않도록 (하고, case이 비교 될 때 실행되는 명령의 패턴을 분리의 구문.
  • ;;case특정 사례 일치를 위해 실행할 명령의 끝을 나타내는 구문입니다 (그리고 실행 후 후속 사례는 테스트하지 않아야 함).

일반 쉘 글 로빙은 *0 개 이상의 문자 ?를 일치시키고 정확히 하나의 문자를 일치 시키며 [ ]괄호 안의 문자 클래스 / 범위를 제공 합니다. 그러나 확장 된 globbing을 사용 하고 있습니다. bash대화식 으로 사용할 때는 기본적으로 확장 글 로빙이 활성화 되지만 스크립트를 실행할 때는 기본적으로 비활성화됩니다. shopt -s extglob스크립트 맨 위에 있는 명령이 켜집니다.

설명 : 확장 글 로빙

*( )@([1-9]*([0-9])|+(0))*( )숫자 입력을 확인 하는 다음 시퀀스와 일치합니다.

  • 0 개 이상의 공백 ( *( )) *( )구조 경기는 0 개 단지 공간 여기에 괄호 안의 패턴의 더.
    실제로 두 가지 종류의 가로 공백, 공백 및 탭이 있으며 종종 탭과 일치하는 것이 바람직합니다. 그러나이 스크립트는 수동, 대화식 입력 및 GNU readline -eread활성화 하는 플래그로 작성되었으므로 걱정하지 않아도 됩니다. 이것은 사용자가 왼쪽 및 오른쪽 화살표 키를 사용하여 텍스트에서 앞뒤로 이동할 수 있도록하지만 일반적으로 탭이 문자 그대로 입력되지 못하게하는 부작용이 있습니다.
  • (한 사건 @( )) 하나의 ( |)
    • 0이 아닌 숫자 ( [1-9]) 다음에 *( )임의의 숫자 ( [0-9]) 중 0 이상 ( ).
    • 중 하나 이상 ( +( ))입니다 0.
  • *( )다시 0 개 이상의 공백 ( )

*( )[qQ]?([uU][iI][tT])*( )quit 명령을 확인 하는 다음 시퀀스와 일치합니다.

  • 0 개 이상의 공백 ( *( ))
  • q또는 Q( [qQ]).
  • 선택적으로, 즉 0 또는 1 회 발생 ( ?( )) :
    • 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쉘 옵션 을 설정할 수 있었고 모든 대소 문자 변형 qquit자동 적용 이 가능했기 때문 입니다.

    이것이 shopt -s nocasematch명령이하는 일입니다. shopt -s extglob명령이 버전에서 사용되지 로빙 생략한다.

  • 정규 표현 기술은 bash의 extglobs에 능숙합니다.

설명 : 정규식

=~연산자 의 오른쪽에 지정된 패턴은 정규 표현식의 작동 방식입니다.

^\ *([1-9][0-9]*|0+)\ *$숫자 입력을 확인 하는 다음 시퀀스와 일치합니다.

  • 선의 시작 (즉, 왼쪽 모서리 ^) ( ).
  • 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 명령을 확인 하는 다음 시퀀스와 일치합니다.

  • 줄의 시작 ( ^).
  • 0 개 이상의 공백 ( \ *위의 설명 참조)
  • 편지 q. 또는가 활성화되어 Q있기 때문 shopt nocasematch입니다.
  • 선택적으로 (즉, ?부분 문자열 ( ( )) 의 0 번 또는 1 번 (postfix ) ) :
    • u, 뒤에 i, 뒤에 t. 또는 shopt nocasematch활성화되어 u있기 때문에 U; 독립적 i으로 I; 그리고 독립적으로, 일 t수있다 T. (즉, 가능성은 및로 제한 되지 않습니다 .)uitUIT
  • 0 개 이상의 공백이 다시 있습니다 ( \ *).
  • 줄 끝 ( $).

3
진실을 말해줘. 시간이 얼마나 걸렸나? ;)
heemayl

4
@heemayl 나는 하루 종일 많은 부분으로 작성했기 때문에 확실하지 않습니다 (게시 직전에 전체 읽기 및 편집이 이어짐). 그래도 시간이 오래 걸리는 것에 대해 생각하고 있다면 시작했을 때 생각했던 것보다 오래 걸리는 것이 확실합니다. :)
Eliah Kagan

6
점점 더 쓰십시오, 나는 당신의 답이 필요한 책이 필요합니다.
Grijesh Chauhan

TL; DR 그러나 어쨌든 나를 웃게했다!
Fabby

제목부터 설명까지 모든 것이 좋습니다. 나는 처음에 그것을 이해했지만 내가 원했기 때문에 다시 읽었습니다
Sumeet Deshmukh

23

이미 기본 아이디어가 있습니다. 이것을 코딩하려면 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

4
-ge사용하고 있기 때문에 이러한 테스트를 제거 할 수 있습니다 elif. 그리고 사랑이 (( $response < X ))없나요?
muru

2
@muru 사실, 감사합니다. 나는 다양한 범위에서 생각하고 있었지만 그럴 이유가 없었습니다. 에 관해서는 (( $response < X )), 그러나 나는 이것을 더 명확하게 생각하고 OP는 분명히 bash 스크립팅에 새로운 것입니다.
terdon

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 일 필요는 없습니다. 시간을내어 좋은 답변을 쓰십시오. terdon 또는 Eliah Kagan의 작동 방식을 살펴보십시오.
muru

@AB 나는이 솔루션이 주로 스타일 변경을 통해 단축 될 수 있지만 여전히 읽을 수 있음을 알았습니다. 간결함이 가장 중요한 고려 사항은 아니기 때문에 이런 방식으로 가지고있는 것을 바꾸어야한다고 생각 하지 않습니다 . 그러나 더 간단한 형식은 공간을 많이 차지하지 않기 때문에 일부 독자는 동일한 방식으로 작동하는 더 짧은 스크립트를 원할 경우이를 표시하는 것을 고려할 수 있습니다. (원한다면 단축 버전이나 그 변형을 자유롭게 사용하십시오.)
Eliah Kagan

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

어떻게 작동합니까?

  1. 입력을 65받습니다.
  2. 시작 부분에 0을 추가하십시오 065.
  3. 마지막 문자를 제거하십시오 06.
  4. 75 그 숫자 빼기- 70.
  5. 문자로 변환하십시오 (A는 65, B는 66)- E.
  6. 인쇄하십시오 E.

내 대명사는


네 생각이 좋아 +1
AB

사용하지 마십시오. 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])))
heemayl

그런 다음 당신은 현재로하지만 잘못 약자로 원래의 코드 too..your 코드를 변형 한 변경할 필요 python3가 없습니다 raw_input()내가 제안 ... raw_input()당신이 사용하여 실행 말한대로 초기 하나 python2..
heemayl를

6

다음 은 배열에 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 .
  • 긍정적으로 생각하는 데 도움이되도록 높은 점수를 먼저 나열합니다. :)
  • 흠, 이것은 일을하고, 그것을 본 후에도 이해가되며, 필수적인 기능을 가지고 있습니다. 실제로 이것을 사용할 수 있습니다!

단점 :

  • 숫자가 아닌 입력을 넣을 때 F를 제공하지만 실제로 그렇게 나쁘지는 않습니다. 숫자가 필요한 곳에 숫자가 아닌 숫자를 주면 F가 필요합니다!
  • 모호한 8 진수 입력은 8 진수로 처리됩니다 ( 1 차원 인덱스 배열 이므로 g). ). 오래된 말로 "버그가 아니라 기능입니다!" 아마도 요
  • 범위를 벗어나거나 숫자가 아닌 입력은 빈 줄을 인쇄합니다. 그래도 실제로 아무런 문제가 없습니다 : 그것은 당신의 입력에 해당하는 문자 등급을 알려주며, 잘못된 입력에 대해서는 하나도 없습니다.
  • 음수를 넣으면 ... 이걸 부활절 달걀 이라고 부릅니다 .
  • Tim의 python 솔루션 보다 훨씬 더 깁니다 . 그래, 나는 그것을 이점처럼 보이기 위해 회전시킬 수 없다.

멋지다, 응? (그래요.)

작동 원리

  1. p함수 (P)은 수치 인덱스 배열 opulates gg의 세 번째 인수로 주어진 (문자) 값과 두 번째 행의 첫번째 인수에 이르기까지의 인덱스 라 데스를.
  2. p 숫자 범위를 정의하기 위해 각 문자 등급에 대해 호출됩니다.
  3. 사용 가능한 한 사용자 입력을 계속 읽 q거나 (또는 Q)로 시작하지 않고 g문자 등급이 입력 된 숫자에 해당하는 배열을 확인하고 해당 문자를 인쇄하십시오.

이 조건은 어떻습니까? [[ $n =~ ^(0|[1-9]+[0-9]*)$ ]]
Helio

6

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

어떻게 작동합니까?

  1. 입력을 65받습니다.
  2. 시작 부분에 0을 추가하십시오 065(그리고 10#10을 밑으로 유지하십시오).
  3. 마지막 문자를 제거하십시오 06.
  4. 75 그 숫자 빼기- 70.
  5. 문자로 변환하십시오 (A는 65, B는 66)- E.
  6. 인쇄하십시오 E.

내 대명사는


매우 영리하고 잘 이루어졌습니다
kos

@ kos thanks :) 그의 범위는 아마도 그가 게시 한 것이 아니기 때문에 OP에 효과가 없을 것입니다 . 나는 이것이 단순함을 기대합니다.
Tim

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"

이제 Perl은 음수 인덱스를 사용하여 배열 끝에서 계산 된 요소를 검색 할 수 있습니다. 예를 들어$arrray[-1] 배열의 마지막 요소를 인쇄합니다. 또한 부동 소수점 배열 인덱스 (예 : 10.7)는 다음으로 낮은 정수 (10.7 또는 10.3 또는 10이되는 모든 것)로 자동으로 잘립니다.

이 모든 결과는 인덱스가 11-($n+1)/10항상 배열의 적절한 요소 (그레이드)로 평가된다는 것입니다.


4
난해한 답변은 모두 훌륭하지만 설명을 포함하십시오.
muru

1

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")

설명

  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목록에 추가 된 것은 존재하지 않기 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.