요약:bash
case
다른 코드의 명령문을 사용하여 입력을 분류하여 입력이 다음과 같은지 확인 하고 싶습니다.
- 양의 정수
- 음의 정수
- 영
- 빈 문자열
- 정수가 아닌 문자열
다음은 다음 입력을 올바르게 분류하는 실행 코드입니다.
- "
word
a\nmultiline\nstring
2.1
-3
하지만 다음 두 개를 음의 정수로 분류해 보세요...:-(
- 0
- 42
세부 사항:
다음을 파일(예 /tmp/integer_case_statement.sh
: ) 에 저장한 chmod
후 실행합니다.
#!/usr/bin/env bash
### This should be a simple `bash` `case` statement to classify inputs as
### {positive|negative|zero|non-} integers.
### Trying extglob, since my previous integer-match patterns failed.
### Gotta turn that on before *function definition* per https://stackoverflow.com/a/34913651/915044
shopt -s extglob
declare cmd=''
function identify() {
local -r it=${1} # no quotes in case it's multiline
# shopt -s extglob # can't do that here
case ${it} in
'')
# empty string, no need for `if [[ -z ...`
>&2 echo 'ERROR: null arg'
;;
?(-|+)+([[:digit:]]))
# it's an integer, so just say so and fallthrough
>&2 echo 'DEBUG: int(it), fallthrough'
;&
-+([[:digit:]]))
# it's negative: just return it
>&2 echo 'DEBUG: int(it) && (it < 0), returning it'
echo "${it}"
;;
0)
# it's zero: that's OK
>&2 echo 'DEBUG: int(it) && (it == 0), returning it'
echo '0'
;;
++([[:digit:]]))
# it's positive: just return it
>&2 echo 'DEBUG: int(it) && (it > 0), returning it'
echo "${it}"
;;
*)
# not an integer, just return it
>&2 echo 'DEBUG: !int(it)'
echo "${it}"
;;
esac
} # end function identify
echo -e "'bash --version'==${BASH_VERSION}\n"
echo "identify '':"
identify ''
echo
# > ERROR: null arg
echo 'identify word:'
identify word
echo
# > DEBUG: !int(it)
# > word
echo 'identify a
multiline
string:'
identify 'a
multiline
string'
echo
# > DEBUG: !int(it)
# > a
# > multiline
# > string
echo 'identify 2.1:'
identify 2.1
echo
# > DEBUG: !int(it)
# > 2.1
echo 'identify -3:'
identify -3
echo
# > DEBUG: int(it), fallthrough
# > DEBUG: int(it) && (it < 0), returning it
# > -3
echo 'identify 0:'
identify 0
echo
# > DEBUG: int(it), fallthrough
# > DEBUG: int(it) && (it < 0), returning it
# > 0
echo 'identify 42:'
identify 42
echo
# > DEBUG: int(it), fallthrough
# > DEBUG: int(it) && (it < 0), returning it
# > 42
exit 0
현재 출력은 파일에 인라인이지만 가독성을 위해 현재 출력은 다음과 같습니다.
'bash --version'==4.3.30(1)-release
identify '':
ERROR: null arg
identify word:
DEBUG: !int(it)
word
identify a
multiline
string:
DEBUG: !int(it)
a
multiline
string
identify 2.1:
DEBUG: !int(it)
2.1
identify -3:
DEBUG: int(it), fallthrough
DEBUG: int(it) && (it < 0), returning it
-3
identify 0:
DEBUG: int(it), fallthrough
DEBUG: int(it) && (it < 0), returning it
0
identify 42:
DEBUG: int(it), fallthrough
DEBUG: int(it) && (it < 0), returning it
42
마지막 두 입력은 내 질문입니다. 사례 설명이 식별되는 이유는 무엇입니까?
- 음의 정수인 0(0이 아님)
- 42 음의 정수(양의 정수 대신)
? 당신의 도움을 주셔서 감사합니다.
답변1
요약:감사해요
또한 부호 있는 0을 감지하기 위한 추가 절과 몇 가지 테스트 사례를 추가했습니다.
세부 사항:
이 향상된 코드를 파일(예 /tmp/integer_case_statement.sh
: ) 에 저장 chmod
하고 실행합니다.
#!/usr/bin/env bash
### Simple `bash` `case` statement to classify inputs as {positive|negative|zero|non-} integers.
### Trying extglob, since my previous integer-match patterns failed.
### Gotta turn that on before *function definition* per https://stackoverflow.com/a/34913651/915044
shopt -s extglob
declare input=''
### For `case` *patterns* (NOT regexps), see
### https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html
function identify() {
local -r it=${1} # no quotes in case it's multiline
# shopt -s extglob # can't do that here
case ${it} in
'')
# empty string, no need for `if [[ -z ...`
>&2 echo 'ERROR: null arg'
;;
[+-]0)
>&2 echo 'ERROR: zero should not be signed'
;;
?(-|+)+([[:digit:]]))
# it's an integer, so just say so and fallthrough
>&2 echo 'DEBUG: int(it), fallthrough'
# ;& # this only runs the next clause, thanks https://unix.stackexchange.com/users/30851/frostschutz
;;& # works
-+([[:digit:]]))
>&2 echo 'DEBUG: it < 0'
;;
0)
>&2 echo 'DEBUG: it == 0'
echo '0'
;;
?(+)+([[:digit:]])) # thanks https://unix.stackexchange.com/users/332764/freddy
>&2 echo 'DEBUG: it > 0'
;;
*)
>&2 echo 'DEBUG: !int(it)'
;;
esac
} # end function identify
echo -e "'bash --version'==${BASH_VERSION}\n"
for input in \
'' \
'@#$%^&!' \
'word' \
'a
multiline
string' \
'2.1' \
'-3' \
'+3' \
'+0' \
'0' \
'-0' \
'42' \
; do
echo "identify '${input}'"
identify "${input}"
ret_val="${?}"
if [[ "${ret_val}" -ne 0 ]] ; then
>&2 echo "ERROR: retval='${ret_val}', exiting ..."
exit 3
fi
echo # newline
done
exit 0
이 Debian 워크스테이션에서 위의 내용은 현재 다음과 같이 출력됩니다.
'bash --version'==4.3.30(1)-release
identify ''
ERROR: null arg
identify '@#$%^&!'
DEBUG: !int(it)
identify 'word'
DEBUG: !int(it)
identify 'a
multiline
string'
DEBUG: !int(it)
identify '2.1'
DEBUG: !int(it)
identify '-3'
DEBUG: int(it), fallthrough
DEBUG: it < 0
identify '+3'
DEBUG: int(it), fallthrough
DEBUG: it > 0
identify '+0'
ERROR: zero should not be signed
identify '0'
DEBUG: int(it), fallthrough
DEBUG: it == 0
0
identify '-0'
ERROR: zero should not be signed
identify '42'
DEBUG: int(it), fallthrough
DEBUG: it > 0
당신의 도움을 주셔서 감사합니다!