case + case 구문에서 같거나 작거나 큰 구현 방법


9

내 목표는 ( case+ 만)으로 숫자 범위를 확인하고 범위를 esac인쇄하는 것입니다. 예를 들어 :

  • 숫자가 0에서 80 사이이면 인쇄 >=0<=80
  • 숫자가 81에서 100 사이이면 인쇄 >=81<=100
  • 기타

아래의 스크립트 문제 >=0<=90는 0에서 9 사이의 숫자 인 경우 에만 인쇄됩니다. 스크립트 를 수정하여 숫자 범위에 따라 올바른 출력을 인쇄하려면 어떻게해야합니까?

#!/bin/ksh
read number 
case $number in 
 [0-80])  echo ">=0<=80";; 
 [81-100]) echo ">=81<=100";; 
 [101-120]) echo ">=101<=120";;
 [121-300]) echo ">=121<=300";;
esac

답변:


6

case단지 패턴 매칭을 위해, 그것은 산술 평가를하지 않을 것입니다 (당신이 생각한다면 어쩌면 제외시켰다 zsh<x-y>확장 패턴 매칭 연산자). 는 [...]단지 일치하는 하나 개의 (또는 문자 조합 소자 내에 지정된 세트에 기초하여 일부 실시 예). 그래서 예를 들면 [0-80]일치하는 것 중 하나 개 가 하나의 경우에 문자를 08하거나 0(즉, 하나의 0, 1, 2, 3, 4, 5, 6, 7, 8).

다음과 같은 패턴으로 숫자를 일치시킬 수 있습니다.

case $(($number)) in
  ([0-9]|[1-7][0-9]|80) echo ">=0<=80";;
  (8[1-9]|9[0-9]|100) echo ">=81<=100";;
  ... and so on
esac

그러나 올바른 도구가 아니라는 것을 쉽게 알 수 있습니다.

[...]일치 하나 개 , 지정된 문자의 목록에 대해 문자를 그래서 [121-300]그와 같은을, 그래서 중 1, 2, 1-3, 0 또는 0 모든 문자에 일치 [0-3]또는 [0123].

사용하다:

if [ "$number" -ge 0 ] && [ "$number" -le 80 ]; then
  echo ">=0<=80"
elif [ "$number" -ge 81 ] &&  [ "$number" -le 100 ]; then
  echo ">=81<=100"
elif ... and so on
  ...
fi

사용하는 다른 방법 case은 다음과 같습니다.

case $((
  (number >= 0 && number <= 80)   * 1 +
  (number > 80 && number <= 100)  * 2 +
  (number > 100 && number <= 120) * 3 +
  (number > 120 && number <= 300) * 4)) in
  (1) echo ">=0<=80";;
  (2) echo ">=81<=100";;
  (3) echo ">=101<=120";;
  (4) echo ">=121<=300";;
  (0) echo "None of the above";;
esac

또는 삼항 연산자 ( x ? y : z)를 사용하십시오 .

case $((
  number >= 0 && number <= 80   ? 1 :
  number > 80 && number <= 100  ? 2 :
  number > 100 && number <= 120 ? 3 :
  number > 120 && number <= 300 ? 4 : 0)) in...

또는 @mikeserv와 같이 상자 밖에서 생각 하고 case논리를 뒤집고 1산술 비교 값과 비교하십시오 .


1
+1을 고려하십시오 if [ n < 0 ] - elif [ n <= 80 ] - elif [ n <= 100 ] ... - else. 타이핑이 적고 오류가 적습니다.
peterph

@peterph 또한 실행하는 데 시간이 더 걸립니다.
Ken Sharp

4

실제로 이것은 정말 쉽습니다. 중요한 것은 case패턴과의 첫 번째 일치를 찾는 데 필요한만큼만 확장한다는 것입니다. 그것은 명시된 행동입니다. 따라서 알려진 문자열로 설정하고 패턴의 확장을 평가할 수 있습니다.

case  1:${number:--} in
(1:*[!0-9]*|1:0*[89]*)
  ! echo NAN
;;
($((number<81))*)
    echo "$number >=0<=80"
;;
($((number<101))*)
    echo "$number >=81<=100"
;;
($((number<121))*)
    echo "$number >=101<=120"
;;
($((number<301))*)
    echo "$number >=121<=300"
;;
esac

case패턴에서 선행 1을 찾기 위해 필요한 것보다 더 많은 패턴을 확장하지 않습니다. 이는 사용자 입력으로 작업 할 때 특히 중요 $number합니다. 이는 실제로 수학 확장에 입력 한 것과 같은 사례 문장에서 산술 확장 컨텍스트에 입력하려고 시도하기 전에 그 내용을 안전하게 확인할 수 있기 때문 입니다.


👍 나는 상자 밖에서 생각하는 방식이 마음에 든다.
Stéphane Chazelas

@ StéphaneChazelas-좋아 case합니다. $((수학으로 할 수있는 멋진 일들 )), case특히 필요할 때까지는 일어나지 않는 패턴의 주변 할당-그리고 alias체인으로 패턴을 채울 경우 중첩 재귀를 확장하는 구문 분석 트리를 만들 수도 있습니다 . 쉘이 문자 변환과 같은 작업을 수행하고 문자를 바이트 값으로 교체하는 가장 빠른 방법입니다. C-Locale ASCII + <> 8 진수는 최악의 경우 7 가지 기본 POSIX 패턴 확장입니다.
mikeserv

1

이것은 좋지는 않지만 이것을 사용할 수 있습니다 :

 #!/bin/ksh

read number  

case $number in
[0-9]|[1-7][0-9]|80) echo  echo ">=0<=80";;
8[1-9]|9[0-9]|100) echo ">=81<=100";;
10[1-9]|11[0-9]|120) echo ">=101<=120";;
12[1-9]|130) echo ">=121<=300";;
esac

"001"또는 "0x99"와 같은 숫자를 커버하기 위해 $ (($ number))로 숫자를 "정식화"하고 싶을 수도 있습니다. "12"와 "12 + 12"도 마찬가지입니다. 바람직하지 않습니다.
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.