나는 셸 스크립트에서 사용자 입력을 구문 분석하는 것입니다. 사용자가 유효한 정수를 제공 한 경우 스크립트는 한 가지 작업을 수행하고 유효하지 않은 경우 다른 작업을 수행합니다. 문제는이 작업을 수행하는 쉽고 (합리적으로 우아한) 방법을 찾지 못했다는 것입니다. 문자별로 구분할 필요가 없습니다.
이게 쉬울 거라는 건 알지만 방법은 모르겠어요. 12 개 언어로 할 수 있지만 BASH는 아닙니다!
내 연구에서 나는 이것을 발견했습니다.
문자열이 10 진법의 유효한 실수로 구성되어 있는지 테스트하기위한 정규식
그리고 거기에 정규식에 대해 이야기하는 대답이 있지만 내가 아는 한 그것은 C에서 사용할 수있는 함수입니다. 그래도 좋은 대답처럼 보였기 때문에 grep으로 시도했지만 grep은 어떻게 해야할지 몰랐습니다. 나는 내 상자에서 PERL 정규 표현식으로 취급한다는 것을 의미하는 -P를 시도했습니다. 대시 E (-E)도 작동하지 않았습니다. 그리고 -F도 마찬가지입니다.
명확하게 말하면, 나는 이와 같은 것을 시도하고, 출력을 찾고 있습니다. 거기에서 내가 얻는 모든 것을 활용하기 위해 스크립트를 해킹 할 것입니다. (IOW, 유효한 라인이 반복되는 동안 부적합한 입력은 아무것도 반환하지 않을 것으로 예상했습니다.)
snafu=$(echo "$2" | grep -E "/^[-+]?(?:\.[0-9]+|(?:0|[1-9][0-9]*)(?:\.[0-9]*)?)$/")
if [ -z "$snafu" ] ;
then
echo "Not an integer - nothing back from the grep"
else
echo "Integer."
fi
누군가 이것이 가장 쉬운 방법을 설명해 주시겠습니까?
솔직히 이것은 TEST의 단점이라고 생각합니다. 다음과 같은 플래그가 있어야합니다.
if [ -I "string" ] ;
then
echo "String is a valid integer."
else
echo "String is not a valid integer."
fi
답변
[[ $var =~ ^-?[0-9]+$ ]]
- 는
^
입력 패턴의 시작을 나타낸다 - 는
-
리터럴 “-“ ?
수단 “0 또는 1 항 (-
)”+
수단 “앞의 1 이상 ([0-9]
)”- 는
$
입력 패턴의 끝을 나타낸다
따라서 정규식은 선택 사항 -
(음수의 경우)과 그 뒤에 하나 이상의 십진수를 일치 시킵니다.
참고 문헌 :
답변
와우 … 여기에 좋은 해결책이 너무 많습니다 !! 위의 모든 솔루션 중에서 -eq
하나의 라이너 를 사용하는 것이 가장 멋지다는 @nortally에 동의합니다 .
GNU bash, 버전 4.1.5
(Debian)을 실행 중 입니다. ksh (SunSO 5.10)에서도 이것을 확인했습니다.
$1
정수인지 아닌지 확인하는 내 버전은 다음과 같습니다 .
if [ "$1" -eq "$1" ] 2>/dev/null
then
echo "$1 is an integer !!"
else
echo "ERROR: first parameter must be an integer."
echo $USAGE
exit 1
fi
이 접근법은 또한 다른 솔루션 중 일부가 잘못된 음수 결과를 갖는 음수를 설명하며 분명히 정수인 “+”(예 : +30) 접두사를 허용합니다.
결과 :
$ int_check.sh 123
123 is an integer !!
$ int_check.sh 123+
ERROR: first parameter must be an integer.
$ int_check.sh -123
-123 is an integer !!
$ int_check.sh +30
+30 is an integer !!
$ int_check.sh -123c
ERROR: first parameter must be an integer.
$ int_check.sh 123c
ERROR: first parameter must be an integer.
$ int_check.sh c123
ERROR: first parameter must be an integer.
Ignacio Vazquez-Abrams가 제공 한 솔루션은 설명 된 후에도 매우 깔끔했습니다 (정규식을 좋아한다면). 그러나 +
접두사 가있는 양수를 처리하지 않지만 다음과 같이 쉽게 수정할 수 있습니다.
[[ $var =~ ^[-+]?[0-9]+$ ]]
답변
여기 파티에 후발. 가장 간단하고 빠르며 휴대 성이 뛰어난 솔루션을 언급 한 답변이 없다는 사실에 매우 놀랐습니다. case
문.
case ${variable#[-+]} in
*[!0-9]* | '') echo Not a number ;;
* ) echo Valid number ;;
esac
비교하기 전에 모든 기호를 잘라내는 것은 약간의 해킹처럼 느껴지지만 case 문에 대한 표현이 훨씬 간단 해집니다.
답변
-eq
테스트를 사용하는 솔루션이 마음에 듭니다. 기본적으로 한 줄짜리이기 때문입니다.
내 해결책은 매개 변수 확장을 사용하여 모든 숫자를 버리고 남은 것이 있는지 확인하는 것이 었습니다. (저는 아직 3.0을 사용하고 있으며 사용하지 않았 [[
거나 expr
이전에 사용했지만 만나서 반갑습니다.)
if [ "${INPUT_STRING//[0-9]}" = "" ]; then
# yes, natural number
else
# no, has non-numeral chars
fi
답변
Bash 3.1 이전 버전으로의 이식성을 위해 ( =~
테스트가 도입 되었을 때 ) expr
.
if expr "$string" : '-\?[0-9]\+$' >/dev/null
then
echo "String is a valid integer."
else
echo "String is not a valid integer."
fi
expr STRING : REGEX
STRING의 시작 부분에 고정 된 REGEX를 검색하여 첫 번째 그룹 (또는 일치하지 않는 경우 일치 길이)을 반영하고 성공 / 실패를 반환합니다. 이것은 오래된 정규식 구문이므로 초과 \
. -\?
“아마도 -
“를 [0-9]\+
의미하고 “하나 이상의 숫자”를 $
의미하며 “문자열의 끝”을 의미합니다.
Bash는 또한 확장 된 glob을 지원하지만 어떤 버전에서 이후 버전인지 기억하지 못합니다.
shopt -s extglob
case "$string" of
@(-|)[0-9]*([0-9]))
echo "String is a valid integer." ;;
*)
echo "String is not a valid integer." ;;
esac
# equivalently, [[ $string = @(-|)[0-9]*([0-9])) ]]
@(-|)
” -
또는 아무것도”를 [0-9]
의미하고 “숫자”를 *([0-9])
의미하며 “0 개 이상의 숫자”를 의미합니다.
답변
여기에 또 다른 방법이 있습니다 (테스트 내장 명령과 반환 코드 만 사용).
function is_int() { return $(test "$@" -eq "$@" > /dev/null 2>&1); }
input="-123"
if $(is_int "${input}");
then
echo "Input: ${input}"
echo "Integer: $[${input}]"
else
echo "Not an integer: ${input}"
fi
답변
숫자가 아닌 것을 제거하고 비교할 수 있습니다. 다음은 데모 스크립트입니다.
for num in "44" "-44" "44-" "4-4" "a4" "4a" ".4" "4.4" "-4.4" "09"
do
match=${num//[^[:digit:]]} # strip non-digits
match=${match#0*} # strip leading zeros
echo -en "$num\t$match\t"
case $num in
$match|-$match) echo "Integer";;
*) echo "Not integer";;
esac
done
테스트 출력은 다음과 같습니다.
44 44 정수 -44 44 정수 44-44 정수 아님 4-4 44 정수 아님 a4 4 정수 아님 4a 4 정수 아님 .4 4 정수 아님 4.4 44 정수 아님 -4.4 44 정수 아님 09 9 정수 아님